Non-techincal brain, is @safe by default good or not?
Mathias LANG
geod24 at gmail.com
Thu May 28 10:28:47 UTC 2020
On Thursday, 28 May 2020 at 07:30:28 UTC, Lutger wrote:
> On Wednesday, 27 May 2020 at 12:59:12 UTC, aberba wrote:
>
>> Now I hearing @safe by default which reads like the plan has
>> changed and now the direction is going all-in on everything
>> MUST BE SAFE. After reading the DIP, I getting a feeling I'll
>> need to re-think my programming model to make everything safe.
>> Sound in my understanding like most code will break.
>> Communist/Socialist kind of coding.
>
> 'everyday programming' in D is almost certainly memory safe,
> except for any c libraries you might use.
I write D on a daily basis. This is most certainly not my
experience. I hear this claim over and over, yet I see no
evidence of it being true. So could you substantiate your claim ?
Let me provide some substance to my own claim. Just right now, I
tried to use Phobos' `std.bitmanip.BitArray`. A bit array is most
certainly `@safe`, right ? Nope, absolutely not.
Okay, that module is old, let's use something that should be
prominent: `std.json`:
```
import std.json;
struct MyCustomType
{
public string toString () const @system { return null; }
alias toString this;
}
void main () @system
{
JSONValue json;
MyCustomType ilovedlang;
json = ilovedlang;
}
```
Results in:
```
/usr/local/opt/dmd/include/dlang/dmd/std/json.d(459): Error:
@safe function std.json.JSONValue.assign!(MyCustomType).assign
cannot call @system function foo.MyCustomType.toString
foo.d(5): foo.MyCustomType.toString is declared here
/usr/local/opt/dmd/include/dlang/dmd/std/json.d(593): Error:
template instance std.json.JSONValue.assign!(MyCustomType) error
instantiating
foo.d(13): instantiated from here: opAssign!(MyCustomType)
```
But... WHY ? My main is `@system`, why do I get a `@safe` error
when I just want to prototype something (in practice, I would not
put any attribute on `toString` but wanted to drive the point
home). Well because someone decided that `std.json` should be
`@safe` and we can't compose attributes easily (as explained
before). Well that right here is our future with `@safe` by
default.
But surely we achieved `@safe`ty, you think ? Well, at what
expense ? If you look at the implementation of `std.json`
(https://github.com/dlang/phobos/blob/5ebf458b509963725e1143b733fba1b22f22ed3f/std/json.d#L450-L533) you'll see that it essentially have to duplicate all its argument to ensure safety (otherwise alias this to function would defeat it). Including associative arrays.
And yet... No we're not `@safe` yet. Some methods (including
`opApply`) are `@system`, which means things like:
```
import std.json;
void main () @safe
{
JSONValue json;
json = [ "Un", "Deux", "trois", "quatre" ];
foreach (idx, val; json.array) { }
}
```
Are not `@safe`. You can see it for a few other functions (e.g.
`object`).
Pick any module in Phobos, and you will find one of three things:
- It is trivial (no user callback, only value types, etc...)
- It can only be used by either `@system` or `@safe` users, not
both;
- It is either overly `@trusted` or everything under the sun is
templated;
Bonus point:
I kinda wanted to find a `@safe`ty failure in Phobos to
illustrate things better.
`std.json` unfortunately looked fairly solid (because of how
limited it is), so I went to the catch-all: `std.algorithm`, more
precisely `std.algorithm.mutation`, because, you know, mutation.
So here we go:
```
import std.algorithm.mutation;
struct S
{
void opPostMove(const ref S old) @system nothrow pure
{
int* ptr = cast(int*)42;
*ptr = 42;
}
int a;
}
void main () @safe nothrow
{
S s1;
s1.a = 41;
S s2 = move(s1); // BOOM
assert(s2.a == 42);
}
```
This compiles and crash just fine.
More information about the Digitalmars-d
mailing list