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