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