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

Paul Backus snarwin at gmail.com
Sun Jul 4 13:19:25 UTC 2021


On Sunday, 4 July 2021 at 08:43:11 UTC, Alexandru Ermicioi wrote:
> On Saturday, 3 July 2021 at 20:09:56 UTC, tsbockman wrote:
>> 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).
>
> Can't remember any specific code now, but suppose you have a 
> mutable object as input to a function or constructor. You need 
> to return or assign an immutable copy of that struct and you 
> can do that with right copy constructor on that object, but 
> before that you need to do a couple of mutations on that 
> object. In this use case you can't avoid cast(immutable) 
> easily. Note: it is desired to not mutate the original object.

```d
immutable(Foo) example(ref Foo input)
{
     Foo mutableCopy = input;
     mutableCopy.mutate();
     return immutable(Foo)(mutableCopy); // call copy ctor
}
```

I guess if your object is very expensive to copy you might want 
to use `cast(immutable)` here, but IMO the real solution is to 
refactor your code so that the call to `.mutate()` is not 
necessary.

For example, let's say that what `mutate` does is change the 
member variable `bar`. You could rewrite the above as:

```d
immutable(Foo) example(ref Foo input)
{
     auto copy = immutable(Foo)(
         // update this field
         computeNewValue(input.bar),
         // copy the rest
         input.baz,
         input.quux,
         /* ... */
     );
     return copy;
}
```


More information about the Digitalmars-d-learn mailing list