Bug 7554 – Immutable function pointer arguments too
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2012-02-20T14:51:00Z
Last change time
2012-02-28T15:35:40Z
Keywords
pull, rejects-valid
Assigned to
nobody
Creator
bearophile_hugs
Comments
Comment #0 by bearophile_hugs — 2012-02-20T14:51:48Z
This problem may be correlated to Issue 7500
This code doesn't compile because 'foo' is mutable:
T outer(T)(T function(in T) pure foo) pure {
pure int inner() {
return foo(5);
}
return inner();
}
int sqr(in int x) pure {
return x * x;
}
void main() {
assert(outer(&sqr) == 25);
}
test.d(3): Error: pure nested function 'inner' cannot access mutable data 'foo'
test.d(11): Error: template instance test.outer!(int) error instantiating
But it doesn't work if you add an 'immutable':
T outer(T)(immutable T function(in T) pure foo) pure {
pure int inner() {
return foo(5);
}
return inner();
}
int sqr(in int x) pure {
return x * x;
}
void main() {
assert(outer(&sqr) == 25);
}
test.d(11): Error: template test.outer(T) cannot deduce template function from argument types !()(int function(const(int) x) pure)
This compiles, but it's not nice:
int sqr(in int x) pure {
return x * x;
}
immutable sqrPtr =&sqr;
auto outer(typeof(sqrPtr) foo) pure {
pure int inner() {
return foo(5);
}
return inner();
}
void main() {
assert(outer(sqrPtr) == 25);
}
A better workaround, found by Timon Gehr:
T outer(T)(T function(in T) pure foo) pure {
immutable fooTick = foo;
pure int inner() {
return fooTick(5);
}
return inner();
}
int sqr(in int x) pure {
return x * x;
}
void main() {
assert(outer(&sqr) == 25);
}
Comment #1 by k.hara.pg — 2012-02-26T08:23:38Z
I think making inner() pure isn't necessary.
Following raises no error and works as expected.
T outer(T)(T function(in T) pure foo) pure {
int inner() {
return foo(5);
}
return inner();
}
int sqr(in int x) pure {
return x * x;
}
void main() {
assert(outer(&sqr) == 25);
}
Comment #2 by bearophile_hugs — 2012-02-26T10:58:27Z
(In reply to comment #1)
> I think making inner() pure isn't necessary.
In this program I want inner() to be pure.
Comment #3 by bearophile_hugs — 2012-02-27T15:27:55Z
This code compiles, but I don't remember if this used to compile even before fixing bug 7500 :
int outer(immutable int function(in int) pure foo) pure {
pure int inner() {
return foo(5);
}
return inner();
}
int sqr(in int x) pure {
return x * x;
}
void main() {
assert(outer(&sqr) == 25);
}
This doesn't compile still:
T outer(T)(immutable T function(T) pure foo) pure {
pure int inner() {
return foo(5);
}
return inner();
}
int sqr(int x) pure {
return x * x;
}
void main() {
assert(outer(&sqr) == 25);
}
Comment #4 by k.hara.pg — 2012-02-27T17:10:21Z
OK. Reduced test case.
int sqr(int x) pure {
return x * x;
}
void main()
{
immutable(int function(int) pure) ifp = &sqr;
// Error: cannot implicitly convert expression (& sqr) of type int function(int x) pure to immutable(int function(int) pure)
}