Best way to make a template function conditionally @trusted

tsbockman thomas.bockman at gmail.com
Sat Apr 3 22:48:01 UTC 2021


On Friday, 2 April 2021 at 19:49:30 UTC, ikod wrote:
> On Thursday, 1 April 2021 at 22:35:01 UTC, tsbockman wrote:
>> Suppose I have a templated struct member function for which I 
>> can compute at compile-time when the function is memory safe, 
>> and when it is not. But, the compiler cannot correctly 
>> determine this automatically.
>
> Compiler should be able to derive safety of templated 
> functions. You may just omit `@safe`/`@trusted`.

The compiler's approach to verifying memory safety is very 
simplistic: it declares a function non-`@safe` if any potentially 
unsafe operation is found in its implementation, without regard 
for the context. It can only ever infer `@safe` or `@system`, 
never `@trusted`.

The reason `@trusted` is in the language at all is to allow the 
programmer to manually mark as memory safe those functions which 
contain operations that would be unsafe in some other context, 
but which the programmer has manually analyzed and verified to be 
incapable of violating memory safety, no matter what inputs it 
receives.

Consider the following program:
```D
import std.stdio;

void writeSafe()(int[2] stuff ...) {
     foreach(n; 0 .. stuff.length)
         writeln(stuff[n]);
}
void writeTrusted()(int[2] stuff ...) {
     foreach(n; 0 .. stuff.length)
         writeln(stuff.ptr[n]);
}

void main() @safe {
     writeSafe(3, 5);
     writeTrusted(3, 5);
}
```

`writeSafe` and `writeTrusted` generate identical code, and are 
equally memory safe in reality. The compiler even knows this on 
some level, because it correctly deduces that the bounds check 
for `stuff[n]` can never fail, and omits it even in `writeSafe`.

Nevertheless, because `.ptr` can be used to violate memory safety 
in other contexts, `writeSafe` is inferred as `@safe`, while 
`writeTrusted` is inferred as `@system`. And so, the program 
above will not compile as it stands.

This is, of course, a trivial example where there is no benefit 
to using the non-`@safe` version, but there are more complex 
cases where the desired algorithm is memory safe as a whole, but 
it cannot be expressed in D without using some operations that 
are forbidden in `@safe` code.


More information about the Digitalmars-d-learn mailing list