Jump to page: 1 2
Thread overview
A purity change
Jul 11, 2013
bearophile
Jul 11, 2013
H. S. Teoh
Jul 11, 2013
Meta
Jul 11, 2013
H. S. Teoh
Jul 11, 2013
monarch_dodra
Jul 11, 2013
Maxim Fomin
Jul 11, 2013
bearophile
Jul 11, 2013
Maxim Fomin
Jul 11, 2013
bearophile
Jul 11, 2013
Maxim Fomin
Jul 11, 2013
monarch_dodra
July 11, 2013
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
July 11, 2013
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
July 11, 2013
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?
July 11, 2013
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.
July 11, 2013
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.
July 11, 2013
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
July 11, 2013
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
July 11, 2013
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.
July 11, 2013
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
July 11, 2013
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
« First   ‹ Prev
1 2