It took me a while to understand Manu's idea for `shared`, and I suspect
that it was/is the same for others. At the same time, Manu seems
bewildered about the objections. I'm going to try and summarize the
situation. Maybe it can help advance the discussion.
(1) How Does Manu's `shared` Interact with @trusted?
With Manu's `shared`, there is implicit conversion from non-`shared` to
`shared`. It would essentially become a language rule. For that rule to
be sound, any access to `shared` data must be @system. And more
challengingly, @system/@trusted code must be written carefully with the
new rule in mind.
(Manu, you might say that the conversion follows from `shared` methods
being "guaranteed threadsafe", but I think it's easier to reason this
way. Anyway, potayto potahto.)
The consequence is: In @trusted code, I have to make sure that I have
exclusive access to any `shared` data that I use. If code that is not
under my control can obtain a non-`shared` view of the same data, I have
failed and my @trusted code is invalid.
An example in code (just rehashing code given by Manu):
----
struct Atomic
{
private int x;
void incr() shared @trusted
{
/* ... atomically increment x ... */
}
/* If this next method is here, the one above is invalid. It's the
responsibility of the author of the @trusted code to make sure
that this doesn't happen. */
void badboy() @safe { ++x; } /* NO! BAD! NOT ALLOWED! */
}
----
(2) What's Wrong with That?
The @trusted contract says that an @trusted function must be safe when
called from an @safe function. That calling @safe function might be
located in the same module, meaning it might have the same level of
access as the @trusted function.
That means, Atomic.incr is invalid. It's invalid whether Atomic.badboy
exists or not. It's invalid because we can even possibly write an
Atomic.badboy. That's my interpretation of the spec, at least.
But according to Manu, Atomic.incr is fine as long as there's no
Atomic.badbody that messes things up. So it looks like we're expected to
violate the @trusted contract when dealing with Manu's `shared`. But
when we routinely have to break the rules, then that's a sign that the
rules are bad.
(3) Maybe It Can Be Made to Work?
There might be a way to implement Atomic without breaking the @trusted
promise:
----
struct Atomic
{
shared/*!*/ int x;
void incr() shared @trusted { /* ... */ }
/* Now this gets rejected by the compiler: */
void badboy() @safe { ++x; } /* compiler error */
}
----
With a `shared int x` there's no way that @safe code might access it, so
the @trusted promise is kept.
Manu, I don't know if marking fields like this is compatible with your
plans. But it would address the @safe-ty issue, I think.
However, even if it's possible to reconcile Manu's `shared` with @safe
and @trusted, that doesn't mean it's automatically golden, of course. It
would be an enormous breaking change that should be well thought-out,
scrutinized, planned, and executed.