how much "real-life" code can be marked @safe ?

tsbockman thomas.bockman at gmail.com
Sat Jul 3 20:09:56 UTC 2021


On Saturday, 3 July 2021 at 16:06:33 UTC, Alexandru Ermicioi 
wrote:
> 3. An edge case. Ex: You need to mutate some data and then 
> assume it is immutable in a constructor.

Can you give a valid example where that is necessary? The main 
examples that I can think of either can be `@safe` with the right 
API, or are motivated by a desire to avoid the GC and/or 
druntime, thus falling under (1).

> 4. Functionality that doesn't account for @safe/immutable or 
> any other features when it can in standard library.

True, although it's just another example of my point (2). The 
standard library and druntime are dependencies, too...

> Take for example array.dup, there is no inout alternative for 
> it,
> and you're pretty much stuck with trusted code, when you'd like 
> to dup an array that is inout.

`inout` is usually just a convenient way to use one 
implementation to handle mutable, `const` and `immutable` cases. 
In those rare cases where `inout` itself won't work, it is almost 
always possible to accomplish the same thing using `template 
this` or separate overloads:

```D
import std.traits : Unqual, CopyConstness;

struct A {
     int*[] arr;
     this(this This, Arr)(Arr arr) scope pure @safe nothrow
         if(is(Arr : E[], E) && is(E : CopyConstness!(This, 
Unqual!E)))
     {
         this.arr = arr.dup;
     }
}

void main()
{
     A ma = new int*[5];
     const(A) ca = new const(int*[3]);
     const(A) ia = new immutable(int*[4]);
}
```

Again, it's certainly not obvious how to do this, or why it is 
necessary, but it is *possible*.

The one exception here is when the array is already typed `inout` 
before it is passed to the constructor. But, that's an example of 
(2) since this logic applies transitively throughout the call 
stack: if you need to call `dup` anywhere, don't erase the 
constness with `inout`.


More information about the Digitalmars-d-learn mailing list