Open burner opened 17 years ago
Bug 2184 has been marked as a duplicate of this bug.
Issue 4331 has been marked as a duplicate of this issue.
The example needs parens:
class Foo { // this() {} invariant { assert (false); } }
void main() { Foo foo = new Foo(); }
Forgot to add the actual parens :o).
class Foo { // this() {} invariant() { assert (false); } }
void main() { Foo foo = new Foo(); }
What should happen in these cases?
class A { shared invariant {} }
class A { immutable invariant {} }
Issue 7334 has been marked as a duplicate of this issue.
import std.stdio;
struct S { invariant() { writeln("invariant"); } // never called // ~this() { writeln("~this"); } // uncomment to call invariant }
Issue 9019 has been marked as a duplicate of this issue.
See also Issue 9454
I agree that the invariant should run on non-empty struct literals and on destruction.
I'm skeptical, however, of the value of running it on default construction, as those values will always be the .init ones.
https://github.com/D-Programming-Language/dmd/pull/4136
(But does not do invariant call for default construction, will change spec to say that isn't don't.)
Documentation fix:
https://github.com/D-Programming-Language/dlang.org/pull/699
Rainer raised an important question for running invariant before class destruction. Because GC finalization order is undetermined an invariant that would check whether some classes's field points to a valid instance could fail because the pointed-to class could already have been finalized.
(In reply to Walter Bright from comment #11)
I'm skeptical, however, of the value of running it on default construction, as those values will always be the .init ones.
Maybe have a rule that, if the -unittest option is set, autogenerate a unittest to call the invariant on the .init.
I stated this elsewhere, just making sure I don't forget: probably we don't want to invoke invariants during the GC cycle.
(In reply to Andrei Alexandrescu from comment #16)
I stated this elsewhere, just making sure I don't forget: probably we don't want to invoke invariants during the GC cycle.
Walter has a different opinion on this, I don't follow his argument though. http://forum.dlang.org/post/m753hk$pt2$1@digitalmars.com
Currently it can't be done, because the calls to the invariant are embedded into the generated destructor function.
Also the invariant is called twice, before and after running the destructor. The latter forces one to perform additional cleanup, e.g. setting pointers to null.
(In reply to Martin Nowak from comment #17)
(In reply to Andrei Alexandrescu from comment #16)
I stated this elsewhere, just making sure I don't forget: probably we don't want to invoke invariants during the GC cycle.
Walter has a different opinion on this, I don't follow his argument though. http://forum.dlang.org/post/m753hk$pt2$1@digitalmars.com
Currently it can't be done, because the calls to the invariant are embedded into the generated destructor function.
Well a simple invariant would be:
assert(this.parent.child is this);
which would be placed in some child node, or could be moved in parent like this:
assert(this.child.parent is this);
The invariant involves two objects no matter where you put it.
Also the invariant is called twice, before and after running the destructor. The latter forces one to perform additional cleanup, e.g. setting pointers to null.
That's definitely a problem. Invariants are not supposed to hold after destruction.
Rebooted as: https://github.com/dlang/dmd/pull/7536/
@RazvanN7 created dlang/dmd pull request #10022 "Fix Issue 519 - Invariant not called from autogenerated class/struct constructor/destructor" fixing this issue:
Maybe this can be done via a caller-side lowering:
The expression T(args...)
would become
{
auto result = T(args...);
assert(() @trusted { return &result; }());
return result;
}()
The @trusted block is to be able to take the address without dip1000.
matti.niemenmaa+dbugzilla reported this on 2006-11-15T07:34:26Z
Transfered from https://issues.dlang.org/show_bug.cgi?id=519
CC List
Description
This code should fail regardless of whether the constructor is commented out or not:
class Foo { // this() {} invariant { assert (false); } }
void main() { Foo foo = new Foo(); }
Yet, it only does if the constructor is explicitly specified. The invariant is not called from the automatically inserted constructor, even though there's no reason why it shouldn't be.