burner / bugzilla_migration_test

0 stars 0 forks source link

Invariant not called from autogenerated class/struct constructor/destructor #12

Open burner opened 17 years ago

burner commented 17 years ago

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.

burner commented 15 years ago

smjg commented on 2009-01-10T11:30:46Z

Bug 2184 has been marked as a duplicate of this bug.

burner commented 14 years ago

bearophile_hugs commented on 2010-06-17T13:08:26Z

Issue 4331 has been marked as a duplicate of this issue.

burner commented 13 years ago

andrei (@andralex) commented on 2010-11-26T11:39:12Z

The example needs parens:

class Foo { // this() {} invariant { assert (false); } }

void main() { Foo foo = new Foo(); }

burner commented 13 years ago

andrei (@andralex) commented on 2010-11-26T11:39:39Z

Forgot to add the actual parens :o).

class Foo { // this() {} invariant() { assert (false); } }

void main() { Foo foo = new Foo(); }

burner commented 13 years ago

yebblies commented on 2011-06-17T07:53:50Z

What should happen in these cases?

class A { shared invariant {} }

class A { immutable invariant {} }

burner commented 13 years ago

k.hara.pg commented on 2011-06-20T05:45:02Z

Autogenerated destructor has same problem:

import core.stdc.stdio : printf; class Foo { invariant() { printf("Foo.invariant\n"); } } void main() { Foo foo = new Foo(); printf("lifetime of foo\n"); delete foo; }

Should print:

Foo.invariant lifetime of foo Foo.invariant

But current output is:

lifetime of foo

burner commented 12 years ago

yebblies commented on 2012-01-21T17:21:31Z

Issue 7334 has been marked as a duplicate of this issue.

burner commented 12 years ago

verylonglogin.reg commented on 2012-10-30T06:05:58Z

Structs have the same problem:

import std.stdio;

struct S { invariant() { writeln("invariant"); } // never called // ~this() { writeln("~this"); } // uncomment to call invariant }

void main() { auto s = S(); }

burner commented 11 years ago

clugdbug commented on 2012-11-15T00:20:52Z

Issue 9019 has been marked as a duplicate of this issue.

burner commented 11 years ago

bearophile_hugs commented on 2013-02-06T03:19:45Z

See also Issue 9454

burner commented 9 years ago

bugzilla (@WalterBright) commented on 2014-11-11T21:11:29Z

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.

burner commented 9 years ago

bugzilla (@WalterBright) commented on 2014-11-12T01:04:15Z

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.)

burner commented 9 years ago

bugzilla (@WalterBright) commented on 2014-11-12T01:47:00Z

Documentation fix:

https://github.com/D-Programming-Language/dlang.org/pull/699

burner commented 9 years ago

code (@MartinNowak) commented on 2014-11-18T18:20:48Z

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.

http://forum.dlang.org/post/m4eu6v$trq$1@digitalmars.com

burner commented 9 years ago

smjg commented on 2014-11-22T02:02:01Z

(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.

burner commented 9 years ago

andrei (@andralex) commented on 2015-01-14T23:43:37Z

I stated this elsewhere, just making sure I don't forget: probably we don't want to invoke invariants during the GC cycle.

burner commented 9 years ago

code (@MartinNowak) commented on 2015-01-15T10:18:44Z

(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.

burner commented 9 years ago

andrei (@andralex) commented on 2015-01-15T16:03:23Z

(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.

burner commented 6 years ago

bugzilla (@WalterBright) commented on 2018-02-09T05:00:19Z

Rebooted as: https://github.com/dlang/dmd/pull/7536/

burner commented 5 years ago

dlang-bot commented on 2019-06-12T11:01:19Z

@RazvanN7 created dlang/dmd pull request #10022 "Fix Issue 519 - Invariant not called from autogenerated class/struct constructor/destructor" fixing this issue:

https://github.com/dlang/dmd/pull/10022

burner commented 1 year ago

qs.il.paperinik commented on 2023-01-13T16:38:49Z

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.