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