Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
On Thu, Sep 12, 2013 at 08:13:37PM +0200, Joseph Rushton Wakeling wrote: > Hi all, > > Suppose that I want to insert some variable values into an assert error message. The easy way to do this is something like: > > assert(someCondition, text("x = ", x, ", cannot blah blah blah")); > > However, the use of text() prevents me from applying @safe and other > such attributes to the function containing this assert, even though > text() will only be called in the event of an assertion failure. > > Is there any reliable way to include variable values in the error message that doesn't interfere with @safe, pure, etc.? Using to!string has a similar problem. [...] 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)); Don't think it will work on 2.063.2, though, since it was a relatively recent change. I suspect this will only work starting from 2.064. T -- MASM = Mana Ada Sistem, Man! |
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
On 12/09/13 20:49, H. S. Teoh wrote:
> 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));
>
> Don't think it will work on 2.063.2, though, since it was a relatively
> recent change. I suspect this will only work starting from 2.064.
Ahh, good to know, thanks. I guess I'll withhold tweaking such things until after the next release ... :-)
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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
Bye,
bearophile
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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. T -- Food and laptops don't mix. |
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
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.
- Jonathan M Davis
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
On 12/09/13 22:07, Jonathan M Davis wrote:
> 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.
The annoyance of this is that it means that any otherwise @safe pure nothrow function that has an assert() in it can be blocked from being nothrow if it needs a formatted string for the assert failure message.
Note that this restriction still applies even if the code is being compiled with -release and the assertion therefore stripped out.
Or am I missing a trick as to how to deal with assert() and enforce() ... ? :-)
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
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); } T -- It won't be covered in the book. The source code has to be useful for something, after all. -- Larry Wall |
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
On Thursday, September 12, 2013 22:17:30 Joseph Rushton Wakeling wrote:
> On 12/09/13 22:07, Jonathan M Davis wrote:
> > 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.
>
> The annoyance of this is that it means that any otherwise @safe pure nothrow function that has an assert() in it can be blocked from being nothrow if it needs a formatted string for the assert failure message.
>
> Note that this restriction still applies even if the code is being compiled with -release and the assertion therefore stripped out.
>
> Or am I missing a trick as to how to deal with assert() and enforce() ... ?
> :-)
You can put the try-catch in a version(assert) block to get around that problem, but it is true that it's not exactly ideal. However, there really isn't any way around that with a function that takes a format string unless you want it to ignore bad arguments. You'd need a function like text which just appends all of its arguments together in order to get around that problem.
- Jonathan M Davis
|
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
On Thu, Sep 12, 2013 at 10:17:30PM +0200, Joseph Rushton Wakeling wrote: > On 12/09/13 22:07, Jonathan M Davis wrote: > >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. > > The annoyance of this is that it means that any otherwise @safe pure nothrow function that has an assert() in it can be blocked from being nothrow if it needs a formatted string for the assert failure message. > > Note that this restriction still applies even if the code is being compiled with -release and the assertion therefore stripped out. > > Or am I missing a trick as to how to deal with assert() and enforce() > ... ? :-) Using assumeWontThrow, as defined in my previous post, you can write this: auto myFunc(int x) nothrow { // Look, ma! This line doesn't violate nothrow! assert(isValid(x), assumeWontThrow!format( "Invalid args (%s), dude!", x)); ... // do work here } :-) T -- "Uhh, I'm still not here." -- KD, while "away" on ICQ. |
September 12, 2013 Re: Safety/purity and assert/enforce error messages | ||||
---|---|---|---|---|
| ||||
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
|
Copyright © 1999-2021 by the D Language Foundation