January 02, 2020
On Thursday, 2 January 2020 at 14:37:02 UTC, Dominikus Dittes Scherkl wrote:
> [snip]
>
> Yes, yes!
> But this tool should not slap @system on every function, but only on those that don't compile with the new default - the rest was already @safe but the proper annotation was missing, so this is the benefit we get. Don't waste it!

You should probably also check that the unittests still pass too...especially if the behavior of the function can change depending on whether something is @safe or not. For instance, in the code below, if you add in @system for foo and baz, then the unittests still compile, but if you make foo and baz @safe, then the unittests no longer pass.

import std;

int foo(int x) {
    static if (isSafe!baz) {
        return baz(x);
    } else {
        return bar(x);
    }
}

@safe int bar(int x) {
    return x + 1;
}

int baz(int x) {
    return x + 2;
}

unittest {
    int x = 5;
    int y = foo(x);
    assert(y == 6);
}
January 02, 2020
On Thursday, 2 January 2020 at 15:02:07 UTC, jmh530 wrote:
> On Thursday, 2 January 2020 at 14:37:02 UTC, Dominikus Dittes Scherkl wrote:
>> [snip]
>>
>> Yes, yes!
>> But this tool should not slap @system on every function, but only on those that don't compile with the new default - the rest was already @safe but the proper annotation was missing, so this is the benefit we get. Don't waste it!
>
> You should probably also check that the unittests still pass too...especially if the behavior of the function can change depending on whether something is @safe or not. For instance, in the code below, if you add in @system for foo and baz, then the unittests still compile, but if you make foo and baz @safe, then the unittests no longer pass.
>
> import std;
>
> int foo(int x) {
>     static if (isSafe!baz) {
>         return baz(x);
>     } else {
>         return bar(x);
>     }
> }
>
> @safe int bar(int x) {
>     return x + 1;
> }
>
> int baz(int x) {
>     return x + 2;
> }
>
> unittest {
>     int x = 5;
>     int y = foo(x);
>     assert(y == 6);
> }

No, this should not be necessary. baz() compiles with @safe as default, so it should not be annotated @system automatically. And if it doesn't compile, that would be a bug in the original code, so it is a good thing that the test now fails.
January 02, 2020
On Thursday, 2 January 2020 at 14:43:50 UTC, ag0aep6g wrote:
> On 02.01.20 14:47, Dominikus Dittes Scherkl wrote:
>> But at the same time, additionally @trusted as a function attribute should be removed and replaced by @trusted expressions. Because:
> [...]
>> @trusted should be restricted to as few code as possible, at best only to the line of code where it is really necessary to make a function @safe.
>
> One step at a time. As it is, the DIP may be disruptive but it's simple. Improvements to @trusted can go in another DIP.
But it is also simple (you just don't need the two pairs of parents at the start and the end of a @trusted lambda anymore) and it affects pretty much exactly the same places as this DIP. The deprecation period will be rather long, so I think it would be a good idea to do both in one wash.

>
> Applying @trusted to as little code as possible sounds good, but it's often done incorrectly
That won't change. You still need to trust things marked as @trusted
(or better: check them again!). This will only be easier if less code is marked such.

> For a caller, there is zero difference between these two functions:
>
>     void f() @trusted { /* ... stuff ... */ }
>     void f() @safe { () @trusted { /* ... the same stuff ... */ } (); }
>
> Having @trusted visible in the function signature just gives people wrong ideas about what it means.
Exactly. That's why forbidding @trusted at function level is a gain.
You loose nothing (you can always replace all trusted functions in the way you illustrated here), but you can improve code a lot.
And you avoid that plenty of new trusted functions suddenly pop up, with no resources to check if they are really @safe or why exactly they are not.
January 02, 2020
On Thursday, 2 January 2020 at 13:49:43 UTC, jmh530 wrote:
> On Thursday, 2 January 2020 at 12:34:05 UTC, bachmeier wrote:
>> [snip]
>>
>> What compiler do you use? I always get error messages when I try to call @system functions from @safe code.
>> [snip]
>
> Nothing prevents you from going function by function to verify if you can make things @trusted or @safe. It would be a big time commitment for legacy code, of course.
>
> Or, you can just make main @system as well.
>
> I think what you are really trying to say is more about interacting between legacy code that was @system by default and new code that is @safe by default. But @system code can call @safe code without any problem. So maybe just write the new code as you please, but then make main @system? There is value in this point. I think most people think it will be quite disruptive.

You would have to go through every function in every library you call as well. That's not realistic, so the outcome would be a programming language where you sometimes have a main function, and sometimes you have a @system main function, and sometimes it matters if you choose one or the other, and sometimes it doesn't. Surely there has to be a better way.

I don't find it helpful to say everything is @system now. That might be true, but it's possible to write @trusted functions right now without attaching the hideous attribute to your function. It's much better to be able to declare that a file contains legacy code and treat everything in that file as @trusted. If you have to add @system to main, that's not only a horrible design, it also defeats the purpose of @safe as the default. If at all possible, this should be handled in such a way that you can continue using code already written, but that disappears as code gets written for @safe by default. The solutions I've seen in this thread are the equivalent of using a chain saw to remove a sliver, and while that would get the job done, it would be worse than no change and also completely unnecessary.

Just to be clear: my proposal is that you add @legacy at the top of a file and everything in there will be @trusted if it's not marked otherwise. If you want compiler errors, don't do anything and the compiler will tell you which functions are not compatible with @safe. You can then mark them @trusted or @system or mark main as @system if you want. But let's not force that crazy solution on everyone.
January 02, 2020
On Thursday, 2 January 2020 at 15:08:41 UTC, Dominikus Dittes Scherkl wrote:
> [snip]
>
> No, this should not be necessary. baz() compiles with @safe as default, so it should not be annotated @system automatically. And if it doesn't compile, that would be a bug in the original code, so it is a good thing that the test now fails.

Under current behavior, baz is @system by default, but that will change to @safe with this DIP. If both baz and foo are annotated with either @safe or @system, then the program (excluding the UTs) compiles without errors. The problem is that the behavior of foo changes if baz is marked @safe rather than @system. You might argue that this is a bug, but it wasn't a bug originally. Your approach would have turned a bug-free program into a buggy one.
January 02, 2020
On Thursday, 2 January 2020 at 15:29:38 UTC, jmh530 wrote:
> On Thursday, 2 January 2020 at 15:08:41 UTC, Dominikus Dittes Scherkl wrote:
>> [snip]
>>
>> No, this should not be necessary. baz() compiles with @safe as default, so it should not be annotated @system automatically. And if it doesn't compile, that would be a bug in the original code, so it is a good thing that the test now fails.
>
> Under current behavior, baz is @system by default, but that will change to @safe with this DIP. If both baz and foo are annotated with either @safe or @system, then the program (excluding the UTs) compiles without errors. The problem is that the behavior of foo changes if baz is marked @safe rather than @system. You might argue that this is a bug, but it wasn't a bug originally. Your approach would have turned a bug-free program into a buggy one.

No, I argue the program was originally buggy: is got the false information that baz is nor safe, but it is only due to a missing annotation (e.g. if buz were a template, it would have been assumed to be @safe)

I hope that very few code out there actually use such bad mechanisms (e.g. call different functions depending on there @safe annotation)-
January 02, 2020
On Thursday, 2 January 2020 at 15:38:22 UTC, Dominikus Dittes Scherkl wrote:
> [...]
Woah, writing fast is not my thing :-/
Again, hopefully with less typos:

> No, I argue the program was originally buggy: it got the false information that baz() is not safe, but this is only due to a missing annotation (e.g. if baz() were a template, it would have been inferred to be @safe)
>
> I hope that very few code out there actually use such bad mechanisms (e.g. call different functions depending on their @safe annotation).


January 02, 2020
On Thursday, 2 January 2020 at 15:29:38 UTC, jmh530 wrote:
> The problem is that the behavior of foo changes if baz is marked @safe rather than @system.

So, +1 migration task:

- [ ] audit uses of isSafe et al.

Excepting assertions, in Phobos, std.range RefRange uses it to
conditionally add @trusted and std.datetime uses it in some
deprecated code.

My response to this DIP was "that sounds great but I hope it
doesn't take forever for the default-default to change." I
think a list of things to check, like this, would help.

These measures may also help:

* --legacy=systemdefault=[fakesafe|system] flag

where 'fakesafe' presents unannotated functions *without* this
flag as if they were @trusted.

* dub.pm stale-package designation.

If a module hasn't been updated since some date, then dub warns
that it's stale while turning the previous flag on for it. This
lets the default-default change *sooner*, which is *better* as
it reduces the truly sucky period of things being up in the
air.

* other stuff?

January 02, 2020
On Thursday, 2 January 2020 at 15:25:15 UTC, bachmeier wrote:
> [snip]
>
> Just to be clear: my proposal is that you add @legacy at the top of a file and everything in there will be @trusted if it's not marked otherwise. If you want compiler errors, don't do anything and the compiler will tell you which functions are not compatible with @safe. You can then mark them @trusted or @system or mark main as @system if you want. But let's not force that crazy solution on everyone.

Your @legacy is really no different than putting @trusted: at the top. I agree with others who are concerned about marking all current code as @trusted, rather than @system.

To your other point about it being ugly to mark main as @system, I recall Walter considering, at some point, keeping main as @system. Perhaps give main more time before changing the default to @safe?


January 02, 2020
On Thursday, 2 January 2020 at 15:50:29 UTC, mipri wrote:
> [snip]
> So, +1 migration task:
>
> - [ ] audit uses of isSafe et al.
>

The et al should probably include at least
__traits(getFunctionAttributes, XXX)
hasFunctionAttributes
functionAttributes
SetFunctionAttributes
isUnsafe