DIP1035 has a design flaw in its current form.
Let us assume it has been implemented as described.
Let us assume a naive user has an extern
variable, which we will use as the example for the whole illustration.
extern int* x;
According to the DIP, since this variable could possibly hold an unsafe value, it is immediately promoted to a @system
variable. Our naive user then tries to write to it in a @safe
setting.
void main() @safe {
*x = 10; // error: @system variable x may not be accessed in @safe code
}
Even if the user reassigns the pointer to a safe value, thus making the actual value safe, the variable is forevermore interpreted by the compiler as @system
.
void fn() @safe {
() @trusted { x = new int; }(); // we're @safe now, right?
*x = 10; // error: @system variable x may not be accessed in @safe code
}
Promoting x
to a @system
variable has had the effect of basically making it unusable. Eventually, the user realizes that the only way solve the problem is to declare the original variable @trusted
.
@trusted extern int* x;
That's what he wanted the whole time. Indeed, that's what everyone who inadvertently initializes a variable to an unsafe value wants. No one ever wants a variable to become permanently unwieldy, just because it may have begun in an unsafe state.
Now let's imagine that a compiler writer realizes this is a common pattern, and wants to improve the error message. So he makes a special flag to mark unsafely initialized variables internally, to distinguish them from explicitly @system
ones. The semantics don't change; it's just a clearer error.
extern int* x;
@system int y;
void fn() @safe {
x = new int; // error: unsafely initialized variable `x` cannot be accessed
// in @safe code - try marking its declaration @trusted?
y++; // error: @system variable y may not be accessed in @safe code
}
We're almost there. The distinction between unsafely-initialized, and explicitly-@system
variables is starting to be felt.
Finally, it dawns on the compiler writers that they've been abusing the user the whole time. They already knew, from the moment the variable was declared, that there was going to be a problem. They had an unsafely-initialized variable. They should have forced the user then and there to say whether it was @trusted
or @system
.
extern int* x; // error: unsafely initialized variables must be explicitly
// annotated with `@trusted`, or `@system`
Boom. We have the real solution to unsafely-initialized global variables.
So that fixes the design flaw.
And it leaves us with a new interpretation of @system
variables. Key points:
-
Implicitly inferring a variable to be
@system
is little more than a form of torture. The user always wanted@trusted
. -
Actual
@system
variables are rare, and never accidental. Being intentionally hard to use, they should only be given to people who ask for them directly.