Bug 6230 – Member functions can no longer be weakly pure

Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-06-30T08:39:00Z
Last change time
2011-08-01T21:44:14Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
kennytm

Comments

Comment #0 by kennytm — 2011-06-30T08:39:36Z
(See http://lists.puremagic.com/pipermail/phobos/2011-June/005487.html and comments in Phobos commit 4f28d** for existing discussion.) After DMD commit 84b4f* a member function can no longer be pure, claiming itself as a nested function. I believe this is a bug because the relevant DMD code Dsymbol *vparent = v->toParent2(); for (Dsymbol *s = sc->func; s; s = s->toParent2()) { if (s == vparent) break; FuncDeclaration *ff = s->isFuncDeclaration(); if (!ff) break; if (ff->setImpure()) { error("pure nested function '%s' cannot access mutable data '%s'", ff->toChars(), v->toChars()); break; } } cannot check the case when 'vparent' is an aggregrate. Nevertheless, this leads to commits d014a and 40def in druntime, and 4f28d in Phobos**, which probably means this bug is INVALID. Test case: ----------------------- struct S { int p; int q() const pure { // <-- Error return p; } } class C { int p; int q() const pure { // <-- Error return p; } } int q2(ref const S s) pure { // <-- Currently OK return s.p; } int q3(ref const C c) pure { // <-- Currently OK return c.p; } ----------------------- y.d(4): Error: pure nested function 'q' cannot access mutable data 'p' y.d(11): Error: pure nested function 'q' cannot access mutable data 'p' ----------------------- * https://github.com/D-Programming-Language/dmd/commit/84b4f ** https://github.com/D-Programming-Language/druntime/commit/d014a https://github.com/D-Programming-Language/druntime/commit/40def https://github.com/D-Programming-Language/phobos/commit/4f28d
Comment #1 by kennytm — 2011-06-30T09:50:12Z
One possible patch: diff --git a/src/expression.c b/src/expression.c index 57cdd61..71f6239 100644 --- a/src/expression.c +++ b/src/expression.c @@ -1366,17 +1366,23 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis) * requiring each function in between to be impure. */ Dsymbol *vparent = v->toParent2(); - for (Dsymbol *s = sc->func; s; s = s->toParent2()) + Dsymbol *s = sc->func, *snext = s->toParent2(); + // Make sure we're really finding parent *functions*, not parent + // class. + if (vparent->isFuncDeclaration() || snext != vparent) { - if (s == vparent) - break; - FuncDeclaration *ff = s->isFuncDeclaration(); - if (!ff) - break; - if (ff->setImpure()) - { error("pure nested function '%s' cannot access mutable data '%s'", - ff->toChars(), v->toChars()); - break; + for (; s; s = s->toParent2()) + { + if (s == vparent) + break; + FuncDeclaration *ff = s->isFuncDeclaration(); + if (!ff) + break; + if (ff->setImpure()) + { error("pure nested function '%s' cannot access mutable data '%s'", + ff->toChars(), v->toChars()); + break; + } } } } diff --git a/src/func.c b/src/func.c index 9957d7f..1cccbed 100644 --- a/src/func.c +++ b/src/func.c @@ -2664,9 +2664,9 @@ enum PURE FuncDeclaration::isPure() TypeFunction *tf = (TypeFunction *)type; if (flags & FUNCFLAGpurityInprocess) setImpure(); - enum PURE purity = tf->purity; - if (purity == PUREfwdref) + if (tf->purity == PUREfwdref) tf->purityLevel(); + enum PURE purity = tf->purity; if (purity > PUREweak && needThis()) { // The attribute of the 'this' reference affects purity strength if (type->mod & (MODimmutable | MODwild)) @@ -2676,6 +2676,9 @@ enum PURE FuncDeclaration::isPure() else purity = PUREweak; } + tf->purity = purity; + // ^ This rely on the current situation that every FuncDeclaration has a + // unique TypeFunction. return purity; }
Comment #2 by kennytm — 2011-07-04T12:25:20Z
Comment #3 by bugzilla — 2011-07-06T20:34:27Z
Comment #4 by bugzilla — 2011-08-01T21:44:14Z