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