www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - pureity of closures

reply "Stefan Koch" <uplink.coder googlemail.com> writes:
dmd infers function closures impure if impure functions are 
defined within them.
even if those are never called and can never be accessed outside 
of the closure.

Example :

int a;
void closure() pure {
   impure_function() {
     a++;
    }
}
t.d(4): Error: pure function 't.closure.impure_function' cannot 
access mutable static data 'a'

is this intended ?
Mar 22 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 22 Mar 2015 12:58:23 +0000, Stefan Koch wrote:

 dmd infers function closures impure if impure functions are defined
 within them.
 even if those are never called and can never be accessed outside of the
 closure.
=20
 Example :
=20
 int a;
 void closure() pure {
    impure_function() {
      a++;
     }
 }
 t.d(4): Error: pure function 't.closure.impure_function' cannot access
 mutable static data 'a'
=20
 is this intended ?
i think it is. you can't do anything with `impure_function` anyway.=
Mar 22 2015
parent reply "Stefan Koch" <uplink.coder googlemail.com> writes:
On Sunday, 22 March 2015 at 18:24:31 UTC, ketmar wrote:

 you can't do anything with `impure_function` anyway.
Precisely my point! a perfectly pure function is inferred impure because of dead code!
Mar 22 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 22 Mar 2015 18:44:47 +0000, Stefan Koch wrote:

 On Sunday, 22 March 2015 at 18:24:31 UTC, ketmar wrote:
=20
 you can't do anything with `impure_function` anyway.
=20 Precisely my point! a perfectly pure function is inferred impure because of dead code!
hm. i missed this part (about dead code). compiler doesn't do "dead=20 nested function removal" before semantic analysis, afair, and attribute=20 inference is in semantic stage. yet you can cheat compiler by turning `impure_function()` to template.=20 attribute inference on templates are done when template is instantiated,=20 and `impure_function()` is never instantiated.=
Mar 22 2015
parent reply "Stefan Koch" <uplink.coder googlemail.com> writes:
On Sunday, 22 March 2015 at 19:06:33 UTC, ketmar wrote:
 hm. i missed this part (about dead code). compiler doesn't do 
 "dead
 nested function removal" before semantic analysis, afair, and 
 attribute
 inference is in semantic stage.

 yet you can cheat compiler by turning `impure_function()` to 
 template.
 attribute inference on templates are done when template is 
 instantiated,
 and `impure_function()` is never instantiated.
I am implementing pure for sdc. The point is, I want to get it right.
Mar 22 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sun, 22 Mar 2015 19:38:52 +0000, Stefan Koch wrote:

 On Sunday, 22 March 2015 at 19:06:33 UTC, ketmar wrote:
 hm. i missed this part (about dead code). compiler doesn't do "dead
 nested function removal" before semantic analysis, afair, and attribute
 inference is in semantic stage.

 yet you can cheat compiler by turning `impure_function()` to template.
 attribute inference on templates are done when template is
 instantiated,
 and `impure_function()` is never instantiated.
=20 I am implementing pure for sdc. The point is, I want to get it right.
i believe that both ways is right (i.e. both generating error and not=20 generating error).=
Mar 22 2015
parent "Stefan Koch" <uplink.coder googlemail.com> writes:
On Sunday, 22 March 2015 at 21:21:59 UTC, ketmar wrote:
 i believe that both ways is right (i.e. both generating error 
 and not
 generating error).
I am sorry but, this is not an helpful answer. I will stick to my callgraph analysis for now.
Mar 23 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 22 March 2015 at 12:58:25 UTC, Stefan Koch wrote:
 dmd infers function closures impure if impure functions are 
 defined within them.
 even if those are never called and can never be accessed 
 outside of the closure.

 Example :

 int a;
 void closure() pure {
   impure_function() {
     a++;
    }
 }
 t.d(4): Error: pure function 't.closure.impure_function' cannot 
 access mutable static data 'a'

 is this intended ?
I think this was not intended and is simply a side effect of limited D call graph analysis. Relaxing that limitation makes sense to me because unused impure function can be used for compile-time reflection or returned from pure function as a result (you need to ensure it does not capture pure functions as closure context in that case)
Mar 23 2015
next sibling parent "Stefan Koch" <uplink.coder googlemail.com> writes:
On Monday, 23 March 2015 at 09:45:41 UTC, Dicebot wrote:

 I think this was not intended and is simply a side effect of 
 limited D call graph analysis. Relaxing that limitation makes 
 sense to me because unused impure function can be used for 
 compile-time reflection or returned from pure function as a 
 result (you need to ensure it does not capture pure functions 
 as closure context in that case)
Yeah that was my guess as well.
Mar 24 2015
prev sibling parent reply Shammah Chancellor <anonymous coward.com> writes:
On 2015-03-23 09:45:39 +0000, Dicebot said:

 I think this was not intended and is simply a side effect of limited D 
 call graph analysis. Relaxing that limitation makes sense to me because 
 unused impure function can be used for compile-time reflection or 
 returned from pure function as a result (you need to ensure it does not 
 capture pure functions as closure context in that case)
Pure functions returning impure functions. *BOOM* My brain just exploded. -Shammah
Mar 27 2015
next sibling parent "Stefan Koch" <uplink.coder googlemail.com> writes:
On Friday, 27 March 2015 at 14:29:05 UTC, Shammah Chancellor 
wrote:
 Pure functions returning impure functions.  *BOOM* My brain 
 just exploded.

 -Shammah
I am not sure when this would happen, but why disallow it ?
Mar 27 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 27 March 2015 at 14:29:05 UTC, Shammah Chancellor 
wrote:
 On 2015-03-23 09:45:39 +0000, Dicebot said:

 I think this was not intended and is simply a side effect of 
 limited D call graph analysis. Relaxing that limitation makes 
 sense to me because unused impure function can be used for 
 compile-time reflection or returned from pure function as a 
 result (you need to ensure it does not capture pure functions 
 as closure context in that case)
Pure functions returning impure functions. *BOOM* My brain just exploded. -Shammah
As long it is exactly the same impure function for given set of arguments (including the context if any) it should comply it pure requirements, shouldn't it?
Mar 27 2015
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Mar 27, 2015 at 05:28:54PM +0000, Dicebot via Digitalmars-d wrote:
 On Friday, 27 March 2015 at 14:29:05 UTC, Shammah Chancellor wrote:
On 2015-03-23 09:45:39 +0000, Dicebot said:

I think this was not intended and is simply a side effect of limited
D call graph analysis. Relaxing that limitation makes sense to me
because unused impure function can be used for compile-time
reflection or returned from pure function as a result (you need to
ensure it does not capture pure functions as closure context in that
case)
Pure functions returning impure functions. *BOOM* My brain just exploded. -Shammah
As long it is exactly the same impure function for given set of arguments (including the context if any) it should comply it pure requirements, shouldn't it?
Makes sense to me. What I'm more concerned about is whether the current compiler implementation may accidentally allow leakage of the pure function's internal context, which would break purity. T -- If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...
Mar 27 2015
parent reply "Stefan Koch" <uplink.coder googlemail.com> writes:
On Friday, 27 March 2015 at 17:47:26 UTC, H. S. Teoh wrote:
 What I'm more concerned about is whether the current compiler
 implementation may accidentally allow leakage of the pure 
 function's
 internal context, which would break purity.


 T
please explain your reasoning with a bit of example code. I am not sure if I get where/when impurity would be introduced.
Mar 29 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 29 March 2015 at 12:29:13 UTC, Stefan Koch wrote:
 On Friday, 27 March 2015 at 17:47:26 UTC, H. S. Teoh wrote:
 What I'm more concerned about is whether the current compiler
 implementation may accidentally allow leakage of the pure 
 function's
 internal context, which would break purity.


 T
please explain your reasoning with a bit of example code. I am not sure if I get where/when impurity would be introduced.
void delegate() metafoo() pure { int x; return () { x = 42; }; // now stack frame of pure function // is available externally // no idea what may happen }
Mar 30 2015
next sibling parent "Meta" <jared771 gmail.com> writes:
On Monday, 30 March 2015 at 13:18:44 UTC, Dicebot wrote:
 On Sunday, 29 March 2015 at 12:29:13 UTC, Stefan Koch wrote:
 On Friday, 27 March 2015 at 17:47:26 UTC, H. S. Teoh wrote:
 What I'm more concerned about is whether the current compiler
 implementation may accidentally allow leakage of the pure 
 function's
 internal context, which would break purity.


 T
please explain your reasoning with a bit of example code. I am not sure if I get where/when impurity would be introduced.
void delegate() metafoo() pure { int x; return () { x = 42; }; // now stack frame of pure function // is available externally // no idea what may happen }
Maybe even better: void delegate() metafoo pure { int x; if (x > 0) { return () => x -= 1; } else { return () => x += 1; } }
Mar 30 2015
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 30 March 2015 at 13:18:44 UTC, Dicebot wrote:
 On Sunday, 29 March 2015 at 12:29:13 UTC, Stefan Koch wrote:
 On Friday, 27 March 2015 at 17:47:26 UTC, H. S. Teoh wrote:
 What I'm more concerned about is whether the current compiler
 implementation may accidentally allow leakage of the pure 
 function's
 internal context, which would break purity.


 T
please explain your reasoning with a bit of example code. I am not sure if I get where/when impurity would be introduced.
void delegate() metafoo() pure { int x; return () { x = 42; }; // now stack frame of pure function // is available externally // no idea what may happen }
Hmmm... Where's the (conceptual) difference to this: struct S { int x; void foo() pure { x = 42; } } S* metafoo() pure { auto s = new S; return s; } Why should your example be impure?
Mar 30 2015