August 26
Walter Bright kirjoitti 26.8.2024 klo 9.20:
> Perhaps that error check on a trusted function call should be suppressed.

No, no, no! `@trusted` means the function body is trusted, not it's call sites.

I'd be in favour if this compiled though, or alternatively reported error in `bar`, not in `foo`:

```
@safe int* foo(int i)
{
    return bar(&i);
}

// unsafe functions that
// intentionally escapes the reference
@trusted
int* bar(scope int* p) { return p; }
```

In real code `bar` like this has no business being `@trusted`, of course, but I have [complained before](https://forum.dlang.org/post/edtbjavjzkwogvutxpho@forum.dlang.org) about non-safe functions inferring DIP1000 attributes themselves.
August 26
Bruce Carneal kirjoitti 25.8.2024 klo 20.55:
> The lesson I take from the DIP 1000 history is that we need something that is simpler to explain, something that is much easier to use correctly, something that models the problem more clearly.

You mean Robert's Simple Safe D. The thing is, Simple Safe D will/would break just as much existing code, because it's the same things - static array slicing and addresses of struct/class fields - that you need to change.

The question is, what are we really annoyed about with DIP1000? If it's because we have too many hotshots who overuse DIP1000 attributes and then expect others to understand it, Simple Safe D would indeed put stop to that. But if it's simply dealing with breakage (my impression), it's going to be the same either way, so better to just improve the experience of dealing with it.

That probably means reining in the `scope` autoinference a bit and make the DIP1000 error message to suggest the GC-using alternatives. As an oversimplification, imagine DMD that understands `scope` / `return scope` when you write them, but always suggests Simple Safe D workarounds when you forget to apply the attributes.
August 26

On Monday, 26 August 2024 at 10:56:06 UTC, Jonathan M Davis wrote:

>

and if I mark up any code as scope to make the compiler happy, that quickly becomes viral, whereas right now, I can just take the address of a local and happily pass it around without any complaints. I just have to mark the function as @trusted
(...)
But using DIP 1000 means that scope has to be used all over the place.

No need! Even with dip1000, you can pass scope values to non-scope parameters in @system or @trusted functions:

void f(char[] str) @safe; // parameter `str` is not marked `scope`

void g() @trusted // checking stack pointer lifetimes manually here
{
    char[32] str;
    f(str[]);
}

The scopeness of str[] ends then and there, no viral application of scope needed.

August 26
I hear you. Let me think about it.
August 26

On Monday, 26 August 2024 at 15:42:28 UTC, Dukc wrote:

>

Bruce Carneal kirjoitti 25.8.2024 klo 20.55:

>

The lesson I take from the DIP 1000 history is that we need something that is simpler to explain, something that is much easier to use correctly, something that models the problem more clearly.

You mean Robert's Simple Safe D.
...

The question is, what are we really annoyed about with DIP1000?
...

My observation was/is that DIP1000 is overly complex for the value provided. This manifests in several ways. There are the, seemingly never ending, holes that get patched. There's the difficulty in explaining how it can be used to full benefit (apart from Timon, and maybe Paul, I don't trust anyone's explanation of what's going on in an even moderately complex dip1000 scenario and, frankly, I'd rather rewrite code than trust even those gurus). There's the methodology being employed wherein we apparently are trying to "prove" safety correctness by observing a fall off in bug reports (as opposed to attributing any fall off to people just moving on). There's the ...

And finally, on a more positive note, there's the belief that we can do much better with a clean sheet design, something with a different model.

There are three paths forward. In my order of preference these are: 1) rethink the whole thing from scratch 2) drop dip1000 and just live with gc/@trusted/... and 3) keep patching and whacking and trying to convince the D community that DIP1000 is worth it.

August 26
On Mon, Aug 26, 2024 at 08:27:31PM +0000, Bruce Carneal via Digitalmars-d wrote: [...]
> My observation was/is that DIP1000 is overly complex for the value provided.
[...]
> There are three paths forward.  In my order of preference these are:  1) rethink the whole thing from scratch  2) drop dip1000 and just live with gc/@trusted/... and 3) keep patching and whacking and trying to convince the D community that DIP1000 is worth it.
[...]

My initial reaction to dip1000 was reservedly positive.  Then it became disappointment, as the number of discovered loopholes and unhandled cases grew.  Finally it settled into indifference, since I don't need any of it in my own code.

It feels like D is trying too hard to be what it isn't. The original design with GC was clean, ergonomic, and productive. This is the core of D that still constitutes the major reason why I'm still using it.  Then the @nogc crowd showed up, and we bent over backwards to please them. As a result, the language was bent out of shape with attribute soup and half-solutions to the wrong problems that did little to improve the experience of existing D users, while still failing to please the GC objectioners.  The past few years' of language extension efforts have felt like a lone wolf clawing at the rest of the universe as it sinks deeper and deeper into a hole it never needed to fall into, while its primary strengths were left stagnating.  The parts of D that are good have not improved much, in spite of gaps and corner cases remaining unfixed over the past decade, while new features that were important only to a minority of users have been tacked on one after another, never really succeeding at making the splash they were intended to make, and only adding more mental load to users who don't need them, and over time just fading into the corner of obscurity of Yet Another Incomplete D Feature.

I feel like saying that it's time for D to admit that it can't be all things to everyone, and to take a stand and decide what it wants to be -- a GC-@safe, ergonomic language with language features geared towards modern GC algorithms, or a low-level, Rust-style manage your own memory, bare minimum C replacement.  But unfortunately I lost confidence that the leadership would be able to take on such a decision effectively, so this is probably all I'll say on this subject.


T

-- 
People tell me I'm stubborn, but I refuse to accept it!
August 26
On Monday, August 26, 2024 12:39:54 PM MDT Dennis via Digitalmars-d wrote:
> On Monday, 26 August 2024 at 10:56:06 UTC, Jonathan M Davis wrote:
> > and if I mark up any code as scope to make the compiler happy,
> > that quickly becomes viral, whereas right now, I can just take
> > the address of a local and happily pass it around without any
> > complaints. I just have to mark the function as @trusted
> > (...)
> > But using DIP 1000 means that scope has to be used all over the
> > place.
>
> No need! Even with dip1000, you can pass scope values to non-scope parameters in `@system` or `@trusted` functions:
>
> ```D
> void f(char[] str) @safe; // parameter `str` is not marked `scope`
>
> void g() @trusted // checking stack pointer lifetimes manually
> here
> {
>      char[32] str;
>      f(str[]);
> }
> ```
>
> The scopeness of `str[]` ends then and there, no viral application of `scope` needed.

Well, that does reduce the problem, but it still means that a function which is perfectly @safe as long as you don't pass it scoped types is either going to have to use scope for scoped types to work, or the caller is going to have to cast away scope. For my own libraries, I'd likely just tell them to cast away scope, but it does add yet another attributes issue where some libraries are going to support it and some won't. And the problem will be worse with templated code - particularly if user-defined types get involved, and they have scope member functions. Attribute inferrence will both reduce the problem by making some stuff just work and increase the problem by introducing scope in places that wouldn't otherwise have it.

As long as you're doing some really basic stuff with pointers and arrays, maybe what DIP 1000 does with scope is restricted enough to be sane, but the problem pretty much has to balloon once you bring user-defined types into the mix - particularly with templated code. Certainly, it was issues with user-defined types and member functions that made me give up on going to the effort of making dxml use DIP 1000 and instead hope that we'd eventually decide to do something other than DIP 1000 which wasn't so hard to figure out and use.

And honestly, if @system and @trusted functions can accept scope data without having to cast away scope, that will probably just increase how much I use @system instead of @safe and overall result in more memory safety issues in my code, whereas right now, the issues that DIP 1000 is looking to help with are pretty rare in my code, since the cases where I take the address of a local or slice a static array are pretty restricted.

But I'm sure that I'll figure out how to make things work with code that I write for myself or other code where I'm dealing with a relatively small number of people who can all get on the same page about what to do about attributes in a particular code base. Ultimately, I expect that the bigger problem is going to be libraries, since they have to deal with users' choices with regards to scope and memory safety.

- Jonathan M Davis



August 27

On Monday, 26 August 2024 at 23:37:36 UTC, Jonathan M Davis wrote:

>

Well, that does reduce the problem, but it still means that a function which is perfectly @safe as long as you don't pass it scoped types is either going to have to use scope for scoped types to work, or the caller is going to have to cast away scope.

As my example showed, there is no cast involved. The cast operator can't even be used for this purpose. All you need is the caller to be @system or @trusted, which without dip1000 must be the case anyway since you're taking the address of a local.

>

And honestly, if @system and @trusted functions can accept scope data without having to cast away scope

It's about whether the call site is @system or @trusted, not the called function.

>

Attribute inferrence will both reduce the problem by making some stuff just work and increase the problem by introducing scope in places that wouldn't otherwise have it.

(...)

>

that will probably just increase how much I use @system instead of @safe and overall result in more memory safety issues in my code,

Are you aware that DIP1000 strictly reduces the amount of @system / @trusted code you need?

And also that adding / inferring scope to a parameter is always a strict improvement for the caller of the function with that parameter?

If you can find a counterexample, where enabling dip1000 would require more @system code without relying on the current bug that slicing locals is allowed in @safe functions, or an example where inferring / adding scope to a parameter adds restrictions to the call site, please post it here or on a bugzilla.

August 27
On Tuesday, August 27, 2024 4:51:26 AM MDT Dennis via Digitalmars-d wrote:
> On Monday, 26 August 2024 at 23:37:36 UTC, Jonathan M Davis wrote:
> > that will probably just increase how much I use @system instead of @safe and overall result in more memory safety issues in my code,
>
> Are you aware that DIP1000 strictly reduces the amount of `@system` / `@trusted` code you need?

It only reduces the amount of @system or @trusted code you need if you're willing to mark up code with scope, which I am not. I'm talking about needing @system and @trusted more in order to avoid the compiler inferring anything as scope or giving me any errors that relate to scope. If DIP 1000 becomes the default, then the amount of @system code in my programs will strictly increase, because I will use @system and @trusted to avoid it entirely.

I am perfectly fine with the status quo of taking the address of local variables being treated as @system, and I don't want to have to mark up any code with scope in order to try to make it @safe. When I did try to deal with DIP 1000, it was too hard to figure out what was going on, and it's simply not solving a problem that I feel needs to be solved.

Right now, taking the address of a local variable results in a very small amount of code being affected, whereas any attempt to have the compiler verify with scope that it's not escaping then requires using scope on all of the places where that pointer or slice is used. It's trading @system for annotations, and I'm utterly sick of the number of annotations in typical D code even when they're not hard to figure out, and with the changes that DIP 1000 adds, scope is way too hard to figure out. Since you've been spending a lot of time and effort working on it, you probably do understand it quite well, but the time that I spent working on it just highlighted for me that it was too much pain for too little gain, and I gave up.

> And also that adding / inferring `scope` to a parameter is always a strict improvement for the caller of the function with that parameter?

I find that hard to believe, because once you start wrapping types with scope member functions, you're going to end up with cases where scope gets inferred, and then the code won't compile if you pass it to something that isn't scope. If that just gets inferred as @system, and the calling code isn't explictly marked as @safe, then maybe there won't be compilation errors, but it was scope inferrence that made me give up on figuring out how to make dxml compile with DIP 1000. It doesn't use scope anywhere and IMHO shouldn't need it, but scope was being inferred on some basis (presumably due to some tests that slice static arrays, since the XML parsing itself doesn't do anything of the sort). It was not obvious how to fix it, and it was complaining about stuff that wasn't actually a problem.

> If you can find a counterexample, where enabling dip1000 would require more `@system` code without relying on the current bug that slicing locals is allowed in `@safe` functions, or an example where inferring / adding `scope` to a parameter adds restrictions to the call site, please post it here or on a bugzilla.

Honestly, I found DIP 1000 hard enough to understand that I gave up on it, and I'm just not willing to spend the time and energy to figure it out at this point. Even if the basic idea is simple, the sum total of it is not even vaguely simple, and it's trying to solve a problem that I simply don't have.

So, maybe I could point out places where it doesn't do what it's supposed to if I spent a bunch of time trying to figure it out, and it's likely that some of what I do understand about it is wrong, but it seems to me that my time will be much better served focusing on other things as long as DIP 1000 is not the default and then figuring out how to completely avoid it if it ever does become the default. It's just too much complexity in an already complex language.

Honestly, if I were making annotation-related changes to D, I would be removing some of the attributes that we already have in order to simplify things. I would not be looking to add more, which is essentially what DIP 1000 is doing even if scope technically already exists in the language.

- Jonathan M Davis



August 27

On Tuesday, 27 August 2024 at 12:16:23 UTC, Jonathan M Davis wrote:

>

It only reduces the amount of @system or @trusted code you need if you're willing to mark up code with scope, which I am not.

No it doesn't. Look at my code example again, there's no scope anywhere in there!

Consider taking the address of a local in all 3 safety scenarios, both before and after enabling dip1000:

No dip1000 dip1000
@system No checks No checks
@trusted No checks No checks
@safe Not allowed Scope checks

Nowhere is there an increase of checks from the left column to the right column. Either you were doing something not allowed to begin with (taking the address of a local in @safe code), or you were already in @system or @trusted code where scope isn't checked.

>

I'm talking about needing @system and @trusted more in order to avoid the compiler inferring anything as scope or giving me any errors that relate to scope.

If you get an error with DIP1000 because of scope, you would have gotten an error without DIP1000 either way because you were taking the address of a local. DIP1000 is strictly not a breaking change.

>

If DIP 1000 becomes the default, then the amount of @system code in my programs will strictly increase, because I will use @system and @trusted to avoid it entirely.

Again, DIP1000 doesn't do scope checks in @system/@trusted code, and won't introduce errors in code that was correctly @safe prior to DIP1000.

>

It's trading @system for annotations

Not trading, but adding an alternative. You can still use @system to avoid DIP1000 checks.

>

and I'm utterly sick of the number of annotations in typical D code even when they're not hard to figure out
(...) the time that I spent working on it just highlighted for me that it was too much pain for too little gain, and I gave up.

I agree, and fully encourage you to not write scope attributes yourself. (I've spent a lot of time fixing wrong applications of return / scope attributes in druntime, Phobos, and certain dub projects.)

>

I find that hard to believe, because once you start wrapping types with scope member functions, you're going to end up with cases where scope gets inferred, and then the code won't compile if you pass it to something that isn't scope.

This is backwards. A scope parameter doesn't turn the argument into a scope value, if anything it removes scope from a value. (E.g. calling .dup on a scope array turns it into a non-scope array because dup's array parameter is scope).

Here's another table of scenarios of passinig arguments to a (scope) parameter:

Parameter storage class: non-scope scope
any argument in @system No error No error
non-scope argument in @safe No error No error
scope argument in @safe Error No error

A strict decrease in errors going to the right column.

>

So, maybe I could point out places where it doesn't do what it's supposed to if I spent a bunch of time trying to figure it out, and it's likely that some of what I do understand about it is wrong, but it seems to me that my time will be much better served focusing on other things as long as DIP 1000 is not the default

I'm completely sympathetic to you not wanting to spend effort reducing code to create DIP1000 bug reports, or refactoring your code to work with scope values. By all means, keep using @trusted / @system code for the few parts that use stack-allocated buffers in your code.

But please understand that unless you consider the current hole in @safe a feature, dip1000 by default will not break your code. If we disallow slicing local variables in @safe under -preview=RobertsSimpleSafeD, then that will break your codebase for real.

Once you fix your code to compile with -preview=RobertsSimpleSafeD, then switching to -preview=dip1000 will not cause any breakage, or it is a bug.