Bug 13113 – cannot build druntime's gc.d with -debug=INVARIANT, bad @nogc inference?
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-07-12T18:04:00Z
Last change time
2014-08-22T08:04:45Z
Assigned to
nobody
Creator
r.sagitario
Comments
Comment #0 by r.sagitario — 2014-07-12T18:04:29Z
When trying to compile gc.d from druntime with -debug=INVARIANT, I get the following error:
gc.d(1367): Error: @nogc function 'gc.gc.Gcx.~this' cannot call non-@nogc function 'gc.gc.Gcx.__invariant'
I've tried reduce this, here's what I get for
//////////////////////
class Gcx
{
~this() {}
invariant()
{
foreach(t; tr) {}
}
Treap!int tr;
}
struct Treap(E)
{
nothrow:
E e;
~this() {}
int opApply(scope int delegate(const ref E) nothrow dg) const
{
return 1;
}
}
///////////////////////
Error: pure function 'nogcinv.Gcx.~this' cannot call impure function 'nogcinv.Gcx.__invariant'
nogcinv.d(5): Error: safe function 'nogcinv.Gcx.~this' cannot call system function 'nogcinv.Gcx.__invariant'
nogcinv.d(5): Error: @nogc function 'nogcinv.Gcx.~this' cannot call non-@nogc function 'nogcinv.Gcx.__invariant'
Comment #1 by r.sagitario — 2014-07-12T18:09:20Z
I'm not 100% sure this is a regression, because the code inside the invariant changed, too.
Is there a reason why the destructor has to be @safe, pure and @nogc?
Comment #2 by safety0ff.bugz — 2014-07-13T09:08:12Z
>Does reverting the invariant portion of [1] allow it to compile?
I haven't actually reverted the code, but commenting out the contents of Gcx.invariant didn't help. Commenting out the destructor of Treap DOES help.
Here is a further reduction of the test case:
class Gcx
{
invariant() {}
Treap!int tr;
}
struct Treap(E)
{
~this() {} // no error if this line is removed
}
Comment #4 by bugzilla — 2014-07-13T19:14:03Z
The trouble seems to be that destructors are getting their attributes inferred, while invariants are not.
This is not a regression, it's a compiler bug around invariant and attributes.
Currently dmd implements both post invariant call in constructor and pre invariant call in destructor as direct call.
But in normal member functions, pre/post invariant call is done virtually.
And, only direct invariant call is affected by the check of pure, @safe, and @nogc attributes. Note that, it is not affected by nothrow but it is not intentional behavior.
class C
{
invariant() {} // impure, throwable, system, and gc-able
this(int) pure nothrow @safe @nogc {} // line 5
// post invaiant is called directly and reports attribute violation error
~this() pure nothrow @safe @nogc {} // line 8
// pre invaiant is called directly and reports attribute violation error
void foo() pure nothrow @safe @nogc {}
// pre/post virtual invariant call does not report attribute violation error
}
Output:
Error: pure function 'test.C.this' cannot call impure function 'test.C.__invariant'
test.d(5): Error: safe function 'test.C.this' cannot call system function 'test.C.__invariant'
test.d(5): Error: @nogc function 'test.C.this' cannot call non-@nogc function 'test.C.__invariant'
Error: pure function 'test.C.~this' cannot call impure function 'test.C.__invariant'
test.d(8): Error: safe function 'test.C.~this' cannot call system function 'test.C.__invariant'
test.d(8): Error: @nogc function 'test.C.~this' cannot call non-@nogc function 'test.C.__invariant'
(In reply to Rainer Schuetze from comment #1)
> I'm not 100% sure this is a regression, because the code inside the
> invariant changed, too.
> Is there a reason why the destructor has to be @safe, pure and @nogc?
So, the original issue is not a compiler regression. It was introduced by druntime change in Gcx class invariant code.
Comment #7 by k.hara.pg — 2014-07-15T03:59:29Z
*** Issue 12834 has been marked as a duplicate of this issue. ***
Comment #8 by r.sagitario — 2014-07-15T07:32:48Z
> So, the original issue is not a compiler regression. It was introduced by druntime change in Gcx class invariant code.
I cannot test the current gc.d code with dmd 2.065 because of other changes, but the reduced test case works with that version. Isn't this a regression for user code, too?
Comment #9 by k.hara.pg — 2014-07-16T04:35:23Z
(In reply to Rainer Schuetze from comment #8)
> > So, the original issue is not a compiler regression. It was introduced by druntime change in Gcx class invariant code.
>
> I cannot test the current gc.d code with dmd 2.065 because of other changes,
> but the reduced test case works with that version. Isn't this a regression
> for user code, too?
OK... make sense.
So, I'd propose that direct invariant calls in constructor and destructor should bypass attribute enforcement.
https://github.com/D-Programming-Language/dmd/pull/3775
Of course it is debatable behavior, but attribute enforcement does not work _at all_ on virtual invariant calls in normal member functions, so the change itself would not make things much worse.
Comment #10 by github-bugzilla — 2014-07-20T21:52:40Z