July 22

On Tuesday, 9 July 2024 at 15:53:04 UTC, Nick Treleaven wrote:

>

That wouldn't be reliable and wouldn't allow safe/unsafe code to interact. We need the code to state what its default is.

A good first step is if a module could state its default. IMO, this makes the most sense. The next edition should have @safe by default and experts(!) can undo that changing their new-edition modules’ default back to @system when it makes sense. Writing system code is an expert activity. D shouldn’t bar experts from their tools, just not expose anyone to them asking for them.

The default should, essentially, be maximal safety. This doesn’t mean you can’t disable those checks, but you have to specifically ask for it.

It means scope plus extra things. scope makes strong guarantees and thus is very useful for avoiding unnecessary allocations. In @safe code, incorrect use will be diagnosed. In @system code, scope is not checked, but nonetheless makes all the guarantees. in (with the preview) is even worse because it means scope, but also looks innocuous. You need expert knowledge to get it right. scope stands out a little more, fortunately, but in? “Oh, this is an input parameter, of course let’s mark it with in to enable some optimizations, that’s what it’s for.” Right, or easily corrupt memory if you don’t also use @safe.

// compile with -preview=in -preview=dip1000

import std.stdio;

const(int)[] global;

void f(in int[] xs) { global = xs; }

void g() { f([1,2,3]); }

void main()
{
    g();
    writeln(global); // (random garbage)
}

Maybe this is just a fluke but to me it feels @system code is getting more dangerous and more expert-only over time.

July 22

On Thursday, 11 July 2024 at 16:16:25 UTC, Walter Bright wrote:

>

On 7/10/2024 11:31 PM, Richard (Rikki) Andrew Cattermole wrote:

>

Yeah I get that, but that is a major problem for things like std.algorithm.

There will be situations without a migration path forward.

Pass @trusted arguments to the templates.

The truth is about every piece of existing code not already annotated is going to fail to compile with safe-by-default. That's been my experience, at least.

The migration path is to mark the stuff with @trusted. You can see that in the dmd source code.

My bet is annotating things @trusted on a large basis is going to end up an eternal makeshift.

My solution is you annotate modules. If you’re a library writer, yes, you’re still out of luck. But as an application writer, if you write default @safe module m; the module’s default is @safe now. Defaults don’t touch templates and other inferred functions, but they do (meaningfully) touch interfaces and higher-order functions. If you’re developing an application and some interface or higher-order function doesn’t work for you after adding some annotation, well, it’s your code. Change it to your needs.

For existing libraries that aren’t annotated, the situation is worse as users may rely on them being @system, e.g. because you (logically) can’t implement a @safe interface method with a @system function. For a higher-order function in a library without attributes, if the function is relatively-safe (i.e. calls with @safe delegate are safe), you can write a @trusted wrapper that just casts the original:

import noattrib;
alias hof = noattrib.hof;
auto hof(void delegate() @safe callback) @trusted => noattrib.hof(callback);
July 22

On Saturday, 13 July 2024 at 19:27:02 UTC, Walter Bright wrote:

>

On 7/13/2024 6:09 AM, Timon Gehr wrote:

>

OpenD has an interesting approach towards default safety. They enabled a large fraction of safety checks in functions without a safety annotation. To disable them, explicit @system is required. This way you get linting benefits even without already ensuring full memory safety guarantees.

It's an interesting approach, but certainly half-baked. How does one decide which safety checks are to be included?

I’d bet all it’s of them except the one telling you that you can’t call a @system function from a @safe function.

July 22
On 7/22/2024 7:14 AM, Quirin Schroll wrote:
> My bet is annotating things `@trusted` on a large basis is going to end up an eternal makeshift.

Perhaps. But it is still up to the user to edit their code to make it @safe, one way or another.

July 22
Mark the arguments to a template as @trusted if they are not safe, and the template will then be safe.

The real issue here is too much unsafe code. There isn't a way to fix that without rolling up one's sleeves and going after it hammer and tong.
July 22
On 7/20/2024 8:55 AM, Timon Gehr wrote:
> My proposal has been to check for bitfield layout best practices by default, to the point of maximum portability.
> Explicit `extern(C)` would be required to turn the checks off.
> 
> I.e., compatible layouts, but D would be more sane.

Ok, I understand that.
July 22
On 7/20/2024 9:10 AM, Timon Gehr wrote:
> You are marking functions as `pragma(local_safe)` one by one while you fix any errors that pop up. The code remains compilable for the entire time. Then once the entire cycle has been fixed, you can replace `pragma(local_safe)` by `@safe`.

How is that different from marking with @trusted?

July 22
On 7/22/24 18:47, Walter Bright wrote:
> Mark the arguments to a template as @trusted if they are not safe, and the template will then be safe.
> ...

No. It will be @safe, but possibly not memory safe. Again, this is pure safewashing. What is even the point of this exercise?
July 22
On 7/22/24 18:51, Walter Bright wrote:
> On 7/20/2024 9:10 AM, Timon Gehr wrote:
>> You are marking functions as `pragma(local_safe)` one by one while you fix any errors that pop up. The code remains compilable for the entire time. Then once the entire cycle has been fixed, you can replace `pragma(local_safe)` by `@safe`.
> 
> How is that different from marking with @trusted?
> 

It will not make the function callable from properly `@safe` code yet, it will just enable some checks. There could be another `pragma` (e.g., `pragma(local_safe, false)` to silence the checks for some portion of the function.

This way you can gradually enable checks without introducing safety lies into the type system. Once all the checks pass, memory safety has been established and you can mark the functions properly `@safe`.

Maybe `pragma(check_safe)` that checks the entire body, even function calls, would be more useful on its own, but we could easily have both.

Anyway, the point is there should be a way to have the compiler help you do this kind of safety scaffolding without you needing to lie to the compiler.
July 22
On Friday, 19 July 2024 at 18:19:38 UTC, Walter Bright wrote:
> On 7/13/2024 2:46 PM, Timon Gehr wrote:
>> Well, your suggestion was to put @trusted _everywhere_, not only on functions with a safe interface. As Dennis points out, it seems that is exactly what happened in some instances.
>
> That is correct.
>
>> Anyway, `@trusted` indicates that whoever put it there reviewed the implementation for memory safety. This makes this approach impractical.
>
> You could call it unwise, or a footgun, or introducing technical debt. But it is practical.
>
> If a surgeon wants to fix a man's heart, first he's going to make things worse by slicing him open like a side of beef.

They use keyhole surgery for a lot of heart ops these days, they fit new values by going in through a vein in your leg for example.


> If a mechanic wants to rebuilt an engine, first he has to dismantle a fair chunk of the car, making things worse.

I think you're making a false equivalence.

Your argument for doing it the way you have is that it's the most effective way of doing it, not that it's the only way to do it. If it were unavoidable there wouldn't even be a debate about it.