July 19

On Friday, 19 July 2024 at 14:57:17 UTC, Quirin Schroll wrote:

>

This is the single best reason to enable @safe by default.

It's also a good example of the pointless debates that go on around here. I know language design is hard. This is not, however. Leave D as unsafe by default and add a switch to enable it, or make it safe by default and add a switch to disable it. It doesn't matter.

It's been debated for years and the solution is trivial. In the meantime, the rest of the programming world has been advancing. This should have been a ten minute decision.

July 19
On Fri, Jul 19, 2024 at 04:03:42PM +0000, Lance Bachmeier via Digitalmars-d wrote:
> On Friday, 19 July 2024 at 14:57:17 UTC, Quirin Schroll wrote:
> 
> > This is the single best reason to enable `@safe` by default.
> 
> It's also a good example of the pointless debates that go on around here. I know language design is hard. This is not, however. Leave D as unsafe by default and add a switch to enable it, or make it safe by default and add a switch to disable it. It doesn't matter.
> 
> It's been debated for years and the solution is trivial. In the meantime, the rest of the programming world has been advancing. This should have been a ten minute decision.

This is typical of the D development process.  Easy decisions are hard, and hard decisions are impossible.  This is why after more than a decade we still don't have a good story for `shared`, while a 10-minute decision like @safe by default has been held up for years simply because of a trivial disagreement (Walter wants @safe to apply to everything, include extern(C), everyone else disagrees on the extern(C) part). In all likelihood it will be another decade before we get @safe by default.

I'm rather tempted to throw my weight behind Adam's fork at this point...


T

-- 
I am Ohm of Borg. Resistance is voltage over current.
July 19
On Friday, 19 July 2024 at 16:17:49 UTC, H. S. Teoh wrote:
> while a 10-minute decision like @safe by default has been held up for years simply because of a trivial disagreement (Walter wants @safe to apply to everything, include extern(C), everyone else disagrees on the extern(C) part).

That wasn't really the main problem. The main problem was breaking existing code. If we proceed with editions, that problem can be solved.
July 19
On 7/11/2024 3:00 AM, Timon Gehr wrote:
> Clearly: `extern(C)` and `extern(D)` bitfields would need to have compatible layouts for syntactically identical declarations that are accepted by both.
> 
> Please understand this simple point, otherwise it makes no sense to continue this debate.

I've never disagreed with that.
July 19
On 7/11/2024 3:09 AM, Timon Gehr wrote:
> If your point is actually that _I_ am in some way the one proposing layout mismatches, well I am not. You would be misrepresenting my point, utterly and absolutely.

Then I apologize, for I thought that was your proposal.

July 19
On 7/17/2024 12:17 PM, Timon Gehr wrote:
> On 7/15/24 20:24, Walter Bright wrote:
>> Those are good suggestions, but I've been trying to make dmd @safe now for a while. With all the inheritance going on, and the flow graph cycles, your suggestions are not workable.
>>
> 
> What I suggested is in fact workable even for code with a big cyclical call graph.


I am not understanding how.
July 19
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.

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


> The solution is to remove the unsafe constructs and then mark everything safe in one go. The compiler currently cannot assist with this very well, but it is easy to do. It should just have a way to enable non-transitive safety checks.

In my experience with large, complex programs, cyclical program flow, that is not practical. I wish it was practical.


> In a data-driven way. They enabled the checks that do not cause too much pain to users. OpenD is a big monorepository with DMD, LDC, and most of the packages that people actually use, so breaking changes actually require breakage to be fixed as well.

I also incrementally fix @safe issues, by making a function temporarily @safe, and fixing what I can. But that does not solve the cyclical dependency problems.


> Anyway, non-transitive checks can be a useful tool for all function attributes, and they have the benefit of not over-specifying their guarantees. This can even be done with pragmas. I implemented a simple pragma to (non-transitively) error out on implicit GC allocations, and it was helpful for performance optimization.

An easier way is just add `@nogc:`, fix all the errors you need to, then remove it.


> Well, if the goal is incremental migration to `@safe`, a process of enabling non-transitive safety checks on a function-by-function basis and then later making it transitive is much more baked than random application of @trusted, and it completely bypasses any issues with big cyclic call graphs.

There is a way:

1. add @safe:

2. fix what you can

3. remove @safe:

No new features required.

July 19

On Friday, 19 July 2024 at 18:19:38 UTC, Walter Bright wrote:

>

In my experience with large, complex programs, cyclical program flow, that is not practical. I wish it was practical.

I assume you're mostly referring to dmd. I've also been incrementally improving dmd's own safety over the years, but by working bottom up, without marking functions with unsafe interfaces @trusted. How do the strategies compare? One approximation would be to simply count additions / deletions of @safe, @system and @trusted in our commits over the last 5 years:

From me:
  @safe:    +1048 -245
  @trusted:  +109 -181
  @system:   +166 -302

From you:
  @safe:     +315 -142
  @trusted: +1331  -46
  @system:   +242  -14

(Generated by https://gist.github.com/dkorpel/666aa59e0b910713f614382f563e89b4 and dmd-master today)

Take these numbers with a grain of salt: this doesn't analyze the scope and actual impact of those attributes of course. However, it's hard to believe mass-applying @trusted on functions is 'the only practical way'.

In my experience, the main obstacles of a @safe dmd are abundant use of __gshared and C-strings. That's why I appreciate your pull requests where you refactor globals into parameters, those improve the @safe situation for real. The DIP idea to make printf's interface @safe is also a step in the right direction because error() calls are everywhere. (though with the bootstrap compiler situation, its usefulness looks very far away).

July 20
On 7/19/24 20:06, Walter Bright wrote:
> On 7/11/2024 3:09 AM, Timon Gehr wrote:
>> If your point is actually that _I_ am in some way the one proposing layout mismatches, well I am not. You would be misrepresenting my point, utterly and absolutely.
> 
> Then I apologize, for I thought that was your proposal.
> 

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.
July 20
On 7/19/24 20:10, Walter Bright wrote:
> On 7/17/2024 12:17 PM, Timon Gehr wrote:
>> On 7/15/24 20:24, Walter Bright wrote:
>>> Those are good suggestions, but I've been trying to make dmd @safe now for a while. With all the inheritance going on, and the flow graph cycles, your suggestions are not workable.
>>>
>>
>> What I suggested is in fact workable even for code with a big cyclical call graph.
> 
> 
> I am not understanding how.

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`.

I guess in practice you'd want some `@system` calls to be flagged while you port, but not others, so some design work may still be needed.

In any case, if I had to port a big codebase to `@safe`, it is likely I would just fork the compiler and create some tooling to help with the job.