Against enforce()
Don
nospam at nospam.com
Fri Mar 18 17:06:16 PDT 2011
Steven Schveighoffer wrote:
> On Fri, 18 Mar 2011 14:35:27 -0400, Don <nospam at nospam.com> wrote:
>
>> Steven Schveighoffer wrote:
>>> On Fri, 18 Mar 2011 04:34:54 -0400, Don <nospam at nospam.com> wrote:
>>>
>>>>> Steven Schveighoffer Wrote:
>>>>>
>>>>>> As long as the delegate does not access shared/global data, it
>>>>>> should be able to be pure. Even delegates which modify TLS data
>>>>>> should be able to be pure (weak-pure, but still pure).
>>>>
>>>> TLS variables are global and must not be accessed from any function
>>>> marked as pure. With regard to purity, there isn't any difference
>>>> between shared and TLS variables.
>>> However, it's still not shared.
>>> This, for example, is a weak pure function:
>>> void foo(int *n) pure { *n = 5;}
>>> Because TLS variables are not shared, you should be able to do this:
>>> int x;
>>> void bar()
>>> {
>>> foo(&x);
>>> }
>>
>> Yes, that compiles fine. But bar() is not pure.
>>
>>> But you are right, there is a huge difference between a local
>>> reference to TLS data and directly accessing TLS data -- the latter
>>> can be obscured from the compiler, resulting in the compiler thinking
>>> the function can be strong pure.
>>> So I don't know exactly how to mitigate this, but in my mind, it
>>> feels like this should work:
>>> int foo(bool cond, lazy int n) pure { if(cond) return n; return 0;}
>>> int x;
>>> void bar()
>>> {
>>> foo(x == 4, x = 5);
>>> }
>>> It seems not too different from the above example where you pass the
>>> address of x. But obviously the x = 5 delegate cannot be pure (it
>>> modifies TLS data).
>>> We may have no recourse to get this to work. It may be a lost
>>> cause, and you just can't have lazy variables for pure functions.
>>
>> It's not a lost cause, it's a two-liner!
>> mtype.c line 5045:
>>
>> if (fparam->storageClass & STClazy)
>> {
>> - error(0, "cannot have lazy parameters to a pure
>> function");
>> + tf->purity = PUREweak;
>> + break;
>> }
>>
>> This is a bit conservative: it would be possible to allow lazy
>> parameters to be marked as pure, which would allow them to be strongly
>> pure. But that would probably not be worth the extra complexity.
>
> I'm not sure this works. Aren't you allowed to pass in a delegate to a
> lazy parameter?
Yes.
>
> For example:
>
> shared int x;
>
> int foo()
> {
> return x;
> }
>
> int bar(lazy int n) pure
> {
> return n;
> }
>
> void baz()
> {
> bar(&foo);
> }
>
> or alternatively:
>
> void baz()
> {
> bar(x);
> }
This compiles just fine. (Well, you need to use bar(foo) not bar(&foo)).
But if you try to mark baz() as pure, here's what you get:
test0.d(135): Error: pure function 'baz' cannot call impure function 'foo'
or for the second case:
test0.d(136): Error: pure function 'baz' cannot access mutable static
data 'x'
bar is just weakly pure.
> The no-shared-data rule prevents you from passing in a shared int
> reference to a pure function, but how do you stop a delegate from
> accessing shared data?
Delegates are either marked as pure, or not. In the case above, foo() is
not pure.
More information about the Digitalmars-d
mailing list