www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Programmer-Controlled ` trusted`

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