Discussion Thread: DIP 1035-- at system Variables--Community Review Round 1
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Wed Jun 17 01:12:49 UTC 2020
Synopsis: this DIP should be best replaced with a series of bug reports
related to @safe. We can't define new features whenever the ones we have
have bugs in them. (Note that accepting the DIP would still allow all of
its egregious examples to compile.)
A few notes:
* The background section should kickstart the narrative, but the general
remarks it makes leave the reader wanting. For example: "This can only
work if the language in which such types are defined has the needed
encapsulation capabilities." to which the obvious question is, "what's
wrong with a struct that puts that thing in a private member and brokers
all access to it?"
* The second example uses:
__traits(getMember, sum, "tag") = 1; // ! ruin integrity of tagged union
The obvious conclusion here is: using __traits(getMember) breaks
encapsulation, therefore it should not be allowed in @safe code. That is
a bug in @safe that needs fixing (regardless of the introduction of
another feature).
The explanation that follows fails to convince:
* "the tag having private visibility only encapsulates at the module
level, while @trusted is applied at the function level, so it can still
be violated by functions in the same module" -> the D protection system
is fundamentally module level. Construing that in an objection for just
this one feature creates the odd precedent that all other encapsulation
primitives should be changed or complemented accordingly. That's well
outside the scope of this one feature.
* "even outside the module, __traits(getMember, ) bypasses private" ->
that's an obvious bug that needs to be fixed.
* <<The tagged union is just one example; there are many other
situations where data should only be modified by code that "knows what
it's doing">> - they call that private.
* "As long as the reference count can be meddled from @safe code,
freeing the memory cannot be @trusted, making @safe reference counting
unsupported in D." -> That means there are bugs in @safe, not a need for
yet another feature with its own liabilities.
* The section title "Existing holes in @safe" contains its own
conclusion. The obvious answer is, great work on documenting them, they
need to be fixed!
* And indeed the example with getPtr() illustrates an obvious bug. Safe
code has no business calling into @system code. It's worth noting,
again, that even if this DIP is approved, that code would continue being
problematic.
* The paragraph about bool's problems even has a reference to an
existing issue. So how does it motivate the introduction of a new feature?
* The quoted Rust discussion is the best argument in the DIP. I don't
know Rust enough to figure whether they have a solution similar to our
@safe/@trusted/@system troika, i.e. I'm not sure they'd have a
workaround just as satisfying as ours. The DIP should discuss that to
establish applicability. (Also, that Rust proposal is quite controversial.)
Speaking of workarounds, aside from fixing the bugs in @safe, I think
someone in need for a system variable can use a little module with:
struct SysVar(T) {
private T value;
ref T get() @system { return value; }
void set(ref T rhs) @system { value = rhs; }
}
Embellishments are immediate (ctors, allowing void init, opAssign, etc).
To the extent this type can be pried open in @safe code, these are
definitely bugs in the existing language.
* The "Alternatives" section should be moved before the bulk of the
proposal. The narrative should go: here's the problem we have, here are
the solution within the existing language, here are the problems with
them, here is the new feature that solves them better.
* "First of all, disallowing the bypassing of private in @safe code is
not sufficient for ensuring struct invariants. As mentioned in the
quote, sometimes invariants need to hold onto types that are not unsafe,
such as int. When there are no pointer members, then private fields can
still be indirectly written to using overlap in a union,
void-initialization, or array casting." -> all of these are unsafe
operations. What am I missing?
* "Finally, it would mean that circumventing visibility constraints
using __traits(getMember, ...) must become @system or deprecated
entirely, similarly to .tupleof. This would break all (@safe) code that
uses this feature, and reintroduces the problems of Issue #15371. All
things considered, making private work with @trusted appears to be a
bigger hassle than introducing checks for @system variables and fields."
-> I don't understand this argument. Yes you should be able to bypass,
just not in @safe code. Yes fixing that would break code, as it should.
Again it's a problem with the feature that won't get solved by adding
another one. I think the best value that can be derived from this DIP
might be the necessity of __traits(getPublicMember, ...).
To conclude, it seems this DIP has great value at documenting, arguing,
and illustrating the failings of @safe, but should at best conclude that
those bugs need fixing.
More information about the Digitalmars-d
mailing list