digitalmars.D - Re: A better assert() [was: Re: std.unittests [updated] for review]
- bearophile <bearophileHUGS lycos.com> Feb 05 2011
- Adam D. Ruppe <destructionator gmail.com> Feb 05 2011
Adam D. Ruppe:LOL!
I like a bit of humour to keep myself serious/sane despite the strange discussions we have around here now and then :-)But, assert(0) does exactly what it says - assert this situation is invariably invalid.Something like class_instance.invariant() is better because: - It's explicit and readable.
So is assert(obj);
An assert(something) doesn't say in any explicit way that it will call the invariant, it's an information present only inside your head, that knows D mysteries. A syntax like class_name.invariant() or something similar is instead explicit in its purpose to call the invariant.This isn't really special. You're asserting the object is valid, which includes the invariant. If you want to only assert it is not null, you should write assert(obj !is null);
The semantics a not D-expert expects from assert(something) is to test that something is "true". For a class reference this means the pointer is not null. If you want assert() to do more for classes/structs/enums, then you are adding a special case to assert().Also, if you change to obj.invariant(), it will probably never be used. assert() is your one-stop shop for sanity tests.
:-)IMO that's the bug. It'd make a lot more sense to fix it so assert(struct) checks the invariant than to break assert(class) so it doesn't.
Removing a special case from assert() doesn't mean breaking it. One more "interesting" example: struct Foo { int x; invariant() { assert(x == 0); } T opCast(T:bool)() { return false; } } void main() { Foo f; assert(f); // line 8 } It generates: core.exception.AssertError test(8): Assertion failure Here the assert(f) is calling opCast, this according to DbC laws makes it call invariant first, here it passes, but then opCast returns a false, and the final assert fails. Bye, bearophile
Feb 05 2011
bearophile:The semantics a not D-expert expects from assert(something) is to test that something is "true". For a class reference this means the pointer is not null.
This is the core of our disagreement: I think an object is not "true" if it's invariant fails. It means the object is completely invalid, no different than if it was a null pointer. It's unusable. The sooner this check is done, the better, so we can figure out where it went wrong.One more "interesting" example:
That makes sense, it's still analogous to if() like you'd expect. Actually, I wonder if doing if(obj) should check it's invariant too with classes, both for consistency with assert and getting that check done even more often.
Feb 05 2011