Forcing weak-pure

Steven Schveighoffer schveiguy at yahoo.com
Tue Mar 25 06:30:04 PDT 2014


There has been an increased effort as of late to make as much as possible  
inside the runtime @safe, pure, and nothrow. The goal is to make it so  
it's not as nasty writing such code, because the library will allow it.  
Everything that we mark properly down below will allow higher-level  
constructs to be marked as well.

Of course naturally, with all things this low-level, we have to make  
decisions as to what is *provably* @safe/pure/nothrow, and what is  
*logically* @safe/pure/nothrow. The most obvious example is memory  
allocation -- It is technically not pure as it accesses global state (the  
heap), but we can rationalize making it pure since we have more logical  
knowledge of the situation than the compiler (i.e. locking the global  
heap, and realizing that if a block is unallocated, it is uniquely  
accessed with the allocation of it).

One issue, however, is modification of heap metadata for immutable data.  
The D compiler has the (correct) rationalization that for a pure function  
that has only immutable or implicitly convertible to immutable parameters,  
it is strong-pure. This means, it can optimize away calls to such  
functions. But in the case of modifying heap metadata, the call is  
actually weak-pure, since it is making modifications that you *don't* want  
to optimize away.

For this reason, 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? One option suggested is to add a  
hidden void * parameter that defaults to null, to force the issue. But I  
think future compilers may be smart enough to realize that can also be a  
strong-pure call.

Another possibility is to pass the array/pointer by reference. This causes  
its own problems with rvalues, and does not help when the array/pointer  
itself is immutable.

Do we need a way (maybe a pragma) to make a function inside druntime  
"forced weak" pure? Is there an option any of you wonderful geniuses out  
there can figure out without changes to the compiler? :)

Some reference material:

https://github.com/D-Programming-Language/druntime/pull/553
https://github.com/D-Programming-Language/druntime/pull/747
https://github.com/D-Programming-Language/phobos/pull/2025
https://github.com/D-Programming-Language/phobos/pull/2046

-Steve


More information about the Digitalmars-d mailing list