On Thu, 07 Jun 2012 13:46:43 -0400, Artur Skawina <[email protected]>
wrote:
On 06/07/12 18:45, Steven Schveighoffer wrote:
On Thu, 07 Jun 2012 11:55:32 -0400, Artur Skawina <[email protected]>
wrote:
On 06/07/12 16:43, Steven Schveighoffer wrote:
I understand the implementation is not correct for shared, and that
actually is my point. The current compiler lets you do the wrong
thing without complaint. Given that the shared version of the
function needs to be written differently than the unshared version,
we gain nothing but bugs by allowing pure functions that operate on
shared.
In essence, a pure-accepting-shared (PAS) function is not
realistically useful from a strong-pure function. A strong-pure
function will have no ties to shared data, and while it may be able
to create data that could potentially be shared, it can't actually
share it! So a PAS function being called from a strong-pure function
is essentially doing extra work (even if it's not implemented, the
expectation is it will be some day) for no reason.
So since a PAS function cannot usefully be optimized (much better to
write an unshared version, it's more accurate), and must be written
separately from the unshared version, I see no good reason to allow
shared in pure functions ever. I think we gain a lot by not allowing
it (more sanity for one thing!)
While it's true that "shared" inside pure functions doesn't _look_
right, can you think
of a case where it is actually wrong, given the pure model currently
in use?
Would inferring templated functions as impure if they access (and not
just reference)
shared data help?
I contend it would make marking a template as pure more useful -- you
can with one keyword ban all use of shared via template parameters on a
template function, given that it does not properly protect shared data
from races.
"not properly protecting shared data from races" is as language issue,
it's not
specific to pure functions or templates. (Note: this does not mean that
"shared"
currently does too little; it in fact does too much, but that's a
completely
different issue)
This
shared Atomic!int x;
void main() { x.inc(); };
will do the right thing, even with your "void inc(T)(ref T i) pure"
template.
Right, but if you want to handle shared too, just don't mark inc as pure.
There isn't any advantage to marking it pure. The compiler will infer
pure when it should. Since pure functions (in the proposed fixed
compiler) cannot handle shared data, there is no need to mark inc pure, it
can always be called from a pure function.
Note that the above, while correct, is not a condition of shared. That it
*can* be made to work isn't a factor of inc.
But I can specify inc is pure, and if shared data isn't allowed, inc can
be *sure* it's not going to be abused. It's entirely possible to look at
the inc function, and reason that it can't be used to make a race bug
(assuming someone doesn't deliberately sabotage the increment operator on
a type by casting away pure).
Yes, it's not actually pure, but that won't be problem in practice
because it
takes a mutable reference as input. You are proposing to disallow this.
I'm not proposing disallowing mutable references, just shared references.
IOW, a function marked as pure that deals with shared data can not be
"truly" pure, and
can not be called from a "really" pure function (as that one would
have to handle shared,
so it couldn't be pure either) - so does it make sense to add new
restrictions now, and
not delay this until the "pure" model is improved?
To what improvements do you refer? I think what is currently in place
is sound design, with incomplete or buggy implementation.
As far as it relates to this i don't see a problem - except for the
"const shared"
case, which does not really make sense - the compiler has to assume
another thread
could have mutated the data, so it cannot take advantage of the fact
that this
thread did not. But I guess it could be useful for statically ensuring
that an
implementation does not modify a r/o view of shared data. In every other
case the
function can't be really pure.
The main improvement needed is real purity for functions that not only
take value
inputs but also const references (including pointers, which then need
similar
treatment inside such functions).
pure functions that take immutable arguments can be optimized for purity
already. I agree there are optimizations that could be enabled that
aren't, but that doesn't make those uses invalid usages of purity. Shared
can be also lumped in there, but my contention is that there's no
usefulness in that construct.
-Steve