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.

Reply via email to