digitalmars.dip.ideas - Programmer-Controlled ` trusted`
- Zach Tollen (101/101) Jan 10 I shared this in a small D Discord about a year ago. I had had
I shared this in a small D Discord about a year ago. I had had some ideas about the way the keywords are used in D, although I don’t necessarily program much in D myself. I just like thinking about it, for rather obscure reasons. This is called “Programmer-Controlled trusted” in contrast to “Language-Restricted trusted”, which is what D has always had. I was looking at the memory safety attributes of Rust, and realized that despite being a language entirely devoted to the idea of memory safety, it nonetheless used only *one* keyword (`unsafe`) whereas D had three (` system`, ` safe`, ` trusted`). These principles were arrived at in Spring of 2024: 1) *All* actions taken by a computer program are *supposed* to be memory-safe. 2) *Most* memory-safe actions can be detected as such by the compiler. So many, in fact, that having to mark the small percentage of potentially-unsafe actions will not be prohibitively distracting in general. Thus, as the consensus seems to be, programmers should be able to assume that every program action which is not marked as dangerous/unsafe is safe. 3) *Most* potentially-*unsafe* actions can be detected automatically by the compiler. In order to ensure that they are safe, therefore, the compiler can require that such actions are manually verified as such (` trusted`). 4) *Some* unsafe actions cannot be detected by the compiler, but *can* be detected by the programmer. Thus a programmer should be able to actively indicate that a given action is potentially unsafe (` system` functions and variables). 5) All potentially-unsafe actions, which have been manually verified to be safe, should be able to be "switched off" at precisely the location of the action, so that no excess is included in the verification. Thus, if the unsafe-but-verified action is an entire function, the function can be marked ` trusted`. If the unsafe-but-verified action is a statement, the statement can be marked ` trusted` (same syntax as `try`). And even if the verified action is a single expression, the programmer should *still* be allowed to mark it ` trusted`. (The most natural D syntax for this would be `cast( trusted)`.) So what we’re dealing with here is a system of *alarms*, and the means by which to *switch them off*. Most safety alarms are built-in, but some can be added manually. And the means to switch them off *must be* up to the programmer. He can cast a wide net, or be extremely specific as the needs of the situation demand. 6) D differs from Rust in that interaction with C is a huge priority. And since C modules are not checked for safety by default, the usability of C modules in D may become prohibitively distracting if every unsafe C action had to be switched off manually. Thus, we need a way to handle C imports without undo inconvenience. To solve this, we return to the principle which states that a programmer should be able to switch off the alarm *wherever* the needs of his situation demand. Thus, ` trusted import awesomeClibrary;` is now allowed. ——— Since posting in the small D Discord last year, *two* separate investigations (first by the leader of the OpenD fork, and then by the mainline D leader) have been conducted into the practical feasibility of having ` safe` be the default. *Both* concluded that some variation of a two- or multi-tiered safety system is preferable to a universal safe-by-default system. They both concluded that the highest level of memory safety which the compiler is capable of detecting would be too burdensome for the casual or non-safety-critical user—and thus a lower, less intrusive tier should be introduced as the default. The above original proposal is nonetheless still suggested, as its cost-benefit profile is essentially orthogonal to whether it applies to just one, or to multiple safety tiers. ——— In order to accelerate the evaluation of "Programmer-Controlled ` trusted`", I will address three points which were brought up when it was first posted: Q: What would be the fate of ` trusted` lambdas? A: It's only where a potentially-unsafe operation (called ` system` in D) occurs, that the compiler should generate an error. And there's no reason to force the programmer to enclose any more than precisely what is considered unsafe, when it is manually verified. This need has always been felt, but was not expressible, so people have been settling for the trusted lambdas because it's simply as close as they could get to being able to tell the compiler exactly what they wanted to trust. Once you can mark statements or individual expressions specifically, there is no further need for ` trusted` lambdas. ` trusted` on any function would remain simply a shorthand for trusting the entire function. But the need for creating a whole function just to trust one statement or expression would obviously no longer exist. Q: Rumor: The Rust language having only one related keyword `unsafe` caused confusion when searching for unsafe code in Rust programs. A: D is actually in a better position than Rust insofar as D already has two keywords (` trusted` and ` system`) for these purposes. What I realized about Rust is that they got away with using only one keyword, because when attached to a code *statement*, `unsafe` means "turn off the alarm." But when attached to a function *signature*, it means "turn *on* the alarm." D by contrast can always use ` system` to turn the alarm *on*, and ` trusted` to turn it off. Thus, searching for ` trusted` will always take you straight to the potentially unsafe code in a project. Q: What about cleanup code? How could you say you want to trust implicit destructors, for example? Someone in the chat suggested `scope(exit) trusted;` as a kind of kludge to be able to trust a function’s cleanup code, which would probably work.
Jan 10