www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - A purity change

reply "bearophile" <bearophileHUGS lycos.com> writes:
This used to compile (probably dmd 2.060):


struct Foo {
     immutable int y;
     void bar(TF)(TF f) pure {
         f(1);
     }
     void spam() pure {
         bar((int x) => y);
     }
}
void main() {}


But now it gives:

test.d(4): Error: pure function 'test.Foo.bar!(immutable(int) 
delegate(int x) nothrow  safe).bar' cannot call impure delegate 
'f'
test.d(7): Error: template instance test.Foo.bar!(immutable(int) 
delegate(int x) nothrow  safe) error instantiating

Is it a correct error?

Bye,
bearophile
Jul 11 2013
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jul 11, 2013 at 05:25:09PM +0200, bearophile wrote:
 This used to compile (probably dmd 2.060):
 
 
 struct Foo {
     immutable int y;
     void bar(TF)(TF f) pure {
         f(1);
     }
     void spam() pure {
         bar((int x) => y);
     }
 }
 void main() {}
 
 
 But now it gives:
 
 test.d(4): Error: pure function 'test.Foo.bar!(immutable(int)
 delegate(int x) nothrow  safe).bar' cannot call impure delegate 'f'
 test.d(7): Error: template instance test.Foo.bar!(immutable(int)
 delegate(int x) nothrow  safe) error instantiating
 
 Is it a correct error?
[...] Hmm. This seems to be a tricky corner case. The delegate itself is impure, as it accesses y which is outside of its definition and isn't part of its arguments; however, in the larger context of spam(), this shouldn't be a problem since y is accessed via 'this', and 'this' is part of spam's input. I'm not sure how feasible it is for the compiler to statically check such cases, though. But IMO we should at least look into this. T -- Why can't you just be a nonconformist like everyone else? -- YHL
Jul 11 2013
parent reply "Meta" <jared771 gmail.com> writes:
On Thursday, 11 July 2013 at 16:14:13 UTC, H. S. Teoh wrote:
 On Thu, Jul 11, 2013 at 05:25:09PM +0200, bearophile wrote:
 Hmm. This seems to be a tricky corner case. The delegate itself 
 is impure, as it accesses y which is outside of its definition 
 and isn't part of its arguments; however, in the larger context 
 of spam(), this shouldn't be a problem since y is accessed via 
 'this', and 'this' is part of spam's input.
Isn't it okay for pure functions to access global immutable state, such as what the delegate is doing here?
Jul 11 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jul 11, 2013 at 06:31:13PM +0200, Meta wrote:
 On Thursday, 11 July 2013 at 16:14:13 UTC, H. S. Teoh wrote:
On Thu, Jul 11, 2013 at 05:25:09PM +0200, bearophile wrote:
Hmm. This seems to be a tricky corner case. The delegate itself is
impure, as it accesses y which is outside of its definition and
isn't part of its arguments; however, in the larger context of
spam(), this shouldn't be a problem since y is accessed via
'this', and 'this' is part of spam's input.
Isn't it okay for pure functions to access global immutable state, such as what the delegate is doing here?
True, I didn't think of that. :) So in this case it looks like a regression. T -- Mediocrity has been pushed to extremes.
Jul 11 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 11 July 2013 at 16:53:30 UTC, H. S. Teoh wrote:
 On Thu, Jul 11, 2013 at 06:31:13PM +0200, Meta wrote:
 On Thursday, 11 July 2013 at 16:14:13 UTC, H. S. Teoh wrote:
On Thu, Jul 11, 2013 at 05:25:09PM +0200, bearophile wrote:
Hmm. This seems to be a tricky corner case. The delegate 
itself is
impure, as it accesses y which is outside of its definition 
and
isn't part of its arguments; however, in the larger context of
spam(), this shouldn't be a problem since y is accessed via
'this', and 'this' is part of spam's input.
Isn't it okay for pure functions to access global immutable state, such as what the delegate is doing here?
True, I didn't think of that. :) So in this case it looks like a regression. T
It's not a global static though. It's a member immutable, but accessed via the (impure) context pointer. It should work, but it's not just straight up global immutable
Jul 11 2013
prev sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Thursday, 11 July 2013 at 15:25:10 UTC, bearophile wrote:
 This used to compile (probably dmd 2.060):


 struct Foo {
     immutable int y;
     void bar(TF)(TF f) pure {
         f(1);
     }
     void spam() pure {
         bar((int x) => y);
     }
 }
 void main() {}


 But now it gives:

 test.d(4): Error: pure function 'test.Foo.bar!(immutable(int) 
 delegate(int x) nothrow  safe).bar' cannot call impure delegate 
 'f'
 test.d(7): Error: template instance 
 test.Foo.bar!(immutable(int) delegate(int x) nothrow  safe) 
 error instantiating

 Is it a correct error?

 Bye,
 bearophile
My guess is that before 2.063 immutable int y was implicitly static, but now it is per instance data which requires context pointer which is deduced to be impure - that why compilation fails (try placing static attribute). In other words, before 2.063 this was a function and now it is a delegate. And delegates currently don't play well with constness/immutability.
Jul 11 2013
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Maxim Fomin:

 My guess is that before 2.063 immutable int y was implicitly 
 static, but now it is per instance data which requires context 
 pointer which is deduced to be impure - that why compilation 
 fails (try placing static attribute). In other words, before 
 2.063 this was a function and now it is a delegate. And 
 delegates currently don't play well with constness/immutability.
I think you are right. So is it right to ask D to infer such delegate as pure? Bye, bearophile
Jul 11 2013
parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Thursday, 11 July 2013 at 17:59:22 UTC, bearophile wrote:
 Maxim Fomin:

 My guess is that before 2.063 immutable int y was implicitly 
 static, but now it is per instance data which requires context 
 pointer which is deduced to be impure - that why compilation 
 fails (try placing static attribute). In other words, before 
 2.063 this was a function and now it is a delegate. And 
 delegates currently don't play well with 
 constness/immutability.
I think you are right. So is it right to ask D to infer such delegate as pure? Bye, bearophile
I think delegate here can be allowed to be pure. However, I wouldn't expect this issue to be fixed soon since it touches a general problem of delegates vs. immutability problem. There were many discussions and DIP but there is still no solution.
Jul 11 2013
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Maxim Fomin:

 My guess is that before 2.063 immutable int y was implicitly 
 static,
Yet, in the code I used to initialize y in the normal constructor of Foo. If now I tag y as static, that's not possible any more (Error: can only initialize static const member scale inside static constructor), so I don't understand again. Bye, bearophile
Jul 11 2013
parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Thursday, 11 July 2013 at 18:03:14 UTC, bearophile wrote:
 Maxim Fomin:

 My guess is that before 2.063 immutable int y was implicitly 
 static,
Yet, in the code I used to initialize y in the normal constructor of Foo. If now I tag y as static, that's not possible any more (Error: can only initialize static const member scale inside static constructor), so I don't understand again. Bye, bearophile
The reason it worked in normal constructor prior the change was probably the same bug. This docs covers the issue - http://dlang.org/changelog.html#staticfields
Jul 11 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 11 July 2013 at 18:28:19 UTC, Maxim Fomin wrote:
 The reason it worked in normal constructor prior the change was 
 probably the same bug.
 This docs covers the issue - 
 http://dlang.org/changelog.html#staticfields
Daym. Who thought it was a good idea to make immutable static by default? Seems I've been confused in my prior answer because of that.
Jul 11 2013