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/d014ahttps://github.com/D-Programming-Language/druntime/commit/40defhttps://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;
}