Against enforce()
Steven Schveighoffer
schveiguy at yahoo.com
Fri Mar 18 12:12:02 PDT 2011
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?
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);
}
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?
-Steve
More information about the Digitalmars-d
mailing list