Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 11, 2013 A purity change | ||||
---|---|---|---|---|
| ||||
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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maxim Fomin | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: A purity change | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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
|
Copyright © 1999-2021 by the D Language Foundation