Forcing weak-pure

Steven Schveighoffer schveiguy at yahoo.com
Tue Mar 25 17:23:36 PDT 2014


On Tue, 25 Mar 2014 19:30:04 -0400, Artur Skawina <art.08.09 at gmail.com>  
wrote:

> On 03/25/14 21:51, Steven Schveighoffer wrote:
>> On Tue, 25 Mar 2014 14:49:27 -0400, Artur Skawina <art.08.09 at gmail.com>  
>> wrote:
>>
>>> On 03/25/14 14:30, Steven Schveighoffer wrote:
>>>> [...] functions like GC.setAttr and assumeSafeAppend cannot be marked  
>>>> pure. For example:
>>>>
>>>> auto str = "hello".idup;
>>>> str = str[0..1];
>>>> str.assumeSafeAppend();
>>>> str ~= "iya";
>>>>
>>>> The compiler could rationally elide the call to assumeSafeAppend if  
>>>> it is pure. We are not using the return value, and the only parameter  
>>>> is immutable. Since pure functions technically have no side effects,  
>>>> this call can be eliminated. A recent compiler change made such calls  
>>>> warnings (not using result of strong-pure function). But  
>>>> assumeSafeAppend really should be weak-pure, because it does have an  
>>>> effect. In essence, you are technically passing to assumeSafeAppend a  
>>>> pointer to the block that contains the slice, not the slice itself.  
>>>> And that block is mutable.
>>>>
>>>> GC.setAttr has similar issues.
>>>>
>>>> How can we force these to be weak-pure?
>>>
>>> Functions returning 'void' and w/o mutable args cannot be logically  
>>> pure,
>>> as long as they aren't no-ops, obviously. While this property could be
>>> used to render them "weak-pure" in d-speak, this (or any other approach
>>> to marking them as such) would not be enough...
>>>
>>>    // assuming 'assumeSafeAppend()' is "weak-pure":
>>>
>>>    string f(string s) pure { s.assumeSafeAppend(); s ~= "d"; return s;  
>>> }
>>>    string a = "abc".idup, b = f(a[0..2]);
>>
>> This could not be elided, because you are using the return value. It  
>> would have to be called at least once.
>>
>> However, I am OK with it being elided for a second call with the same  
>> input. In other words, this strong pure function does not have the same  
>> issues.
>
> It's ok to treat allocator and factory functions as pure, because those  
> really
> are logically pure, ie can't affect any /visible/ state and return  
> results that
> are unique.
> 'assumeSafeAppend()' does have side effects - it can lead to corruption  
> of other,
> not directly related, data. The only thing that prevents this is a  
> declaration
> by the programmer -- "Trust me, I own this data and there are no other  
> live aliases".
> The problem is that this declaration would now happen /implicitly when  
> calling
> a (strongly) pure function/.
> Note that the 'a' string in the above example could no longer be "abc"  
> after 'f()'
> runs.
> The "pure" concept (re-)definition in D is bad enough even without  
> having to worry
> about supposedly pure functions stomping on unrelated data.

You what I wasn't thinking of? parallelization of pure function calls!  
Right there, that kills this whole idea.

In fact, I think at this point, any operation to immutable arrays that  
affects the metadata for that block, including setting length and  
appending, must be by definition impure.

This is not a good turn of events...

-Steve


More information about the Digitalmars-d mailing list