assumeSafeAppend and purity

Steven Schveighoffer schveiguy at yahoo.com
Mon Feb 6 18:40:55 PST 2012


On Mon, 06 Feb 2012 21:28:49 -0500, Steven Schveighoffer  
<schveiguy at yahoo.com> wrote:

> On Mon, 06 Feb 2012 21:18:21 -0500, Vladimir Panteleev  
> <vladimir at thecybershadow.net> wrote:
>
>> On Tuesday, 7 February 2012 at 02:02:22 UTC, Jonathan M Davis wrote:
>>> On Tuesday, February 07, 2012 02:54:40 Vladimir Panteleev wrote:
>>>> On Tuesday, 7 February 2012 at 01:47:12 UTC, Jonathan M Davis
>>>>  wrote:
>>>> > At present, assumeSafeAppend isn't pure - nor is capacity or
>>>> > reserve. AFAIK, none of them access any global variables > aside
>>>> > from GC-related stuff (and new is already allowed in pure
>>>> > functions). All it would take to make them pure is to mark > the
>>>> > declarations for the C functions that they call pure (and > those
>>>> > functions aren't part of the public API) and then mark them > as
>>>> > pure. Is there any reason why this would be a _bad_ idea?
>>>>  pure void f(const(int)[] arr)
>>>> {
>>>> 	debug /* bypass purity check to pretend assumeSafeAppend is pure
>>>> */
>>>> 	{
>>>> 		assumeSafeAppend(arr);
>>>> 	}
>>>> 	arr ~= 42;
>>>> }
>>>>  void main()
>>>> {
>>>> 	int[] arr = [0, 1, 2, 3, 4];
>>>> 	f(arr[1..$-1]);
>>>> 	assert(arr[4] == 4, "f has a side effect");
>>>> }
>>>
>>> Except that assumeSafeAppend was misused. It's dangerous to use when  
>>> you don't use it properly regardless of purity. By its very nature, it  
>>> can screw stuff up.
>>
>> When reviewing @safe or pure code, there is inevitably a list of  
>> language features that reviewers need to be aware of as bypassing the  
>> guarantees that said language features provide, for example  
>> assumeUnique, calling @trusted functions, or faux-pure functions which  
>> may lead to side effects. It's a question of how big do we want to let  
>> this list grow.
>>
>> The situation where assumeSafeAppend may be misused due to a bug, but  
>> the source of the bug is "hidden out of sight" because it happens  
>> inside a pure function, is imaginable. Personally, I never use  
>> assumeSafeAppend often enough to justify a potential headache later on.
>
> by the definition of assumeSafeAppend, using it, and then using data in  
> the now 'unallocated' space results in undefined behavior.  It should  
> definitely not be marked @safe or @trusted, but pure should be ok.

I thought of a better solution:

pure T[] pureSafeShrink(T)(ref T[] arr, size_t maxLength)
{
    if(maxLength < arr.length)
    {
        bool safeToShrink = (arr.capacity == arr.length);
        arr = arr[0..maxLength];
        if(safeToShrink) arr.assumeSafeAppend(); // must workaround purity  
here
    }
    return arr;
}

This guarantees that you only affect data you were passed.

-Steve


More information about the Digitalmars-d mailing list