Bug 3316 – Functions nested in a pure templated function cannot reference its local variables

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2009-09-13T16:17:00Z
Last change time
2015-06-09T01:26:47Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
peng2cheng2

Comments

Comment #0 by peng2cheng2 — 2009-09-13T16:17:31Z
import std.stdio; /* ATTEMPT TO USE NESTED "PURE" FUNCTIONS IN A TEMPLATE. All works fine unless you uncomment the third line in main. If you do, dmd 2.032 yeilds: pure.d(35): Error: pure nested function 'bar' cannot access mutable data 'fooState' pure.d(36): Error: pure nested function 'bar' cannot access mutable data 'y' pure.d(47): Error: template instance pure.fooPT!(char) error instantiating */ //"pure" inner function, with concrete types - ok pure string foo(string x, string y){ string fooState; string bar(string x){ fooState = "hello "; return x ~ y; } return fooState ~ bar(x); } //potentially pure (?) templated version not labled as pure - ok immutable(T)[] fooT(T)(immutable(T)[] x, immutable(T)[] y){ immutable(T)[] fooState; immutable(T)[] bar(immutable(T)[] x){ fooState = "hello "; return x ~ y; } return fooState ~ bar(x); } //attempt to make templated version pure - no dice pure immutable(T)[] fooPT(T)(immutable(T)[] x, immutable(T)[] y){ immutable(T)[] fooState; immutable(T)[] bar(immutable(T)[] x){ fooState = "hello "; return x ~ y; } return fooState ~ bar(x); } void main(){ writeln(foo("p", "c")); writeln(fooT("p", "c")); //writeln(fooPT("p", "c"));
Comment #1 by clugdbug — 2009-09-29T23:56:55Z
This is happening because the nested template is being marked as pure. This happens in mtype.c, in TypeFunction::semantic, line 4038: the template function gets marked as pure/nothrow because it's taken from the parent scope. This is wrong, because pure/nothrow shouldn't be inherited by members. PATCH: In DeclarationExp::semantic(Scope *sc), pure (and nothrow) should not be passed on to members. Turn it off while running semantic on those functions. Index: expression.c =================================================================== --- expression.c (revision 196) +++ expression.c (working copy) \@@ -4505,8 +4505,12 @@ } if (!s->isVarDeclaration()) { + // 'pure nothrow' is not inherited by member declarations + int scopePureNothrow = sc->stc & (STCpure | STCnothrow); + sc->stc ^= scopePureNothrow; declaration->semantic(sc); s->parent = sc->parent; + sc->stc ^= scopePureNothrow; } if (!global.errors) {
Comment #2 by clugdbug — 2009-10-21T06:41:44Z
Fixed DMD2.035.