April 30
On 4/29/2025 8:25 PM, Richard (Rikki) Andrew Cattermole wrote:
> 1. Ban all pointers. System handles and with that coroutines/fibers are all @trusted and @system so it doesn't effect them. Anything else should be using the GC and therefore unaffected by this restriction.

Memory unsafety happens when there's a pointer into the reference counted object that is a direct pointer.


> 2. Let the backend handle optimizations. Reference counting primitives are improving (at least in LLVM). Worst case scenario, we have the exact same performance as we do now, but with a better user experience.

Performance problems come from:

1. using a mutex (not an issue for thread local data)

2. needing an exception handler for the decrement

3. increment

4. decrement-test-free

April 30
On 4/29/2025 5:24 PM, Luna wrote:
> My personal opinion on the matter has softened a bit over time. I do think @live could overall be a nice addition to the language. Much like how @nogc is an opt in, there are cases where opting in to borrow checking would be interesting. So as an opt-in attribute I’d not mind it being in the language; I’m only opposed to it being enforced. My strong feelings in the past was mainly down to that. Didn’t want to end up having it forced on me everywhere. As long as dlang keeps its own identity and doesn’t try to become rust, I at least think it’d be an ok change nowadays.

I agree that @live should be opt-in.
May 01
On Wednesday, 30 April 2025 at 01:26:14 UTC, jmh530 wrote:
> And my sense is that DIP 1000 and @live haven't quite gotten us to the place where people want the language to be. That could be a driver to the lack of interest.

I'm playing with DIP 1000, mainly because I'm also playing with @safe and want to be able to pass pointers to local variables in to functions.  (This is using DIP1000, DIP1021 and preview=in together with @safe.)

Note I want to use pointers, not references so as to improve local reasoning about the code.
May 01
On 01/05/2025 10:53 AM, Walter Bright wrote:
> On 4/29/2025 8:25 PM, Richard (Rikki) Andrew Cattermole wrote:
>> 1. Ban all pointers. System handles and with that coroutines/fibers are all @trusted and @system so it doesn't effect them. Anything else should be using the GC and therefore unaffected by this restriction.
> 
> Memory unsafety happens when there's a pointer into the reference counted object that is a direct pointer.

Right, if you don't have the escape analysis to protect the owner, banning all pointers surrounding the RC type solves it inherently.

I don't like the idea of banning all pointers, but it does solve the problem for system handles since they are not regular code. Which is the purpose of having RC in the language (for my motivation).

>> 2. Let the backend handle optimizations. Reference counting primitives are improving (at least in LLVM). Worst case scenario, we have the exact same performance as we do now, but with a better user experience.
> 
> Performance problems come from:
> 
> 1. using a mutex (not an issue for thread local data)
> 
> 2. needing an exception handler for the decrement
> 
> 3. increment
> 
> 4. decrement-test-free

Why are you treating these as new costs? I don't understand.
They are already being paid for with copy constructors and destructors.

But if you are want to remove it, it can be solved.
My plan was to solve this with my DFA framework.

However, for a dedicated solution:

1. Put the add call into the called function as part of the calling convention (extremely important).

2. If a variable declaration has a RC type, flag the function declaration as containing RC during semantic 3.

3. If a function contains RC, call optimization DFA iff optimizations are turned on (speed is not a concern if optimizations are turned off).

4. Use a stack, a nice simple one.

4.1. When you see an add, add the call to the stack.

4.2. When you see end of scope, remove all add's in stack corresponding to that stack.

4.2.1. If a removed add does not have the flag that it is required, disable it and its corresponding sub.

4.3. If mutation event occurs on a variable, find its last add in stack, flag it as requried.

4.3.1. A mutation event is anything that could mutate the variable, i.e. ref, out, taking a pointer, assignment.

5. Do not codegen any expression that has been marked as disabled.

You do not need control flow block handling for this.
If it cannot disable calls, its because they are needed.


```d
void func(RC input) {
    input.add; // elidable
    scope(exit)
		input.sub; // elidable

    if (condition) {
        input.sub;
        input = RC(...);
        input.add;
    }
}
```

6 days ago
On 01/05/2025 2:28 PM, Richard (Rikki) Andrew Cattermole wrote:
> ```d
> void func(RC input) {
>      input.add; // elidable
>      scope(exit)
>          input.sub; // elidable
> 
>      if (condition) {
>          input.sub;
>          input = RC(...);
>          input.add;
>      }
> }
> ```

Ok that example is bad, no sub oops.

I came up with this optimization solution a long time ago and may have forgot a few things.

6 days ago
On 4/30/2025 7:28 PM, Richard (Rikki) Andrew Cattermole wrote:
> Why are you treating these as new costs? I don't understand.
> They are already being paid for with copy constructors and destructors.

Pointers and references are used to avoid needing copy/destroy


> However, for a dedicated solution:

It's an interesting approach. I recommend hand-coding it, and testing the performance.

6 days ago
On 4/30/2025 7:51 PM, Richard (Rikki) Andrew Cattermole wrote:
> I came up with this optimization solution a long time ago and may have forgot a few things.

No prob. Happens to me all the time!

6 days ago
On 01/05/2025 6:08 PM, Walter Bright wrote:
>     However, for a dedicated solution:
> 
> It's an interesting approach. I recommend hand-coding it, and testing the performance.

I am unconvinced that such test code would be worth trying to benchmark.

On the newer x86 cpu's we're talking 1-8uops for atomic operations.

And test code tends not to reflect the problem domain, which for system handles involves a lot of costly syscalls and IPC, that make atomics and with that system lock basically free.

In saying that, unnecessary work is still unnecessary and removing it is a good thing. However I won't miss the optimizations, but I do miss not having classes that are RC (going with struct wrapper can result in CT errors).

6 days ago
On Tuesday, 29 April 2025 at 17:12:41 UTC, Walter Bright wrote:
> I caveat my remarks with although I've have studed the Rust specification, I have not written a line of Rust code.
>

https://github.com/rust-lang/polonius

https://gcc.gnu.org/pipermail/gcc-patches/2025-March/677874.html

from this news in Russian:
https://www.opennet.ru/opennews/art.shtml?num=62924
5 days ago
On Wed, 30 Apr 2025 at 03:16, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> I caveat my remarks with although I've have studed the Rust specification,
> I
> have not written a line of Rust code.
>
> I was quite intrigued with the borrow checker, and set about learning
> about it.
> While D cannot be retrofitted with a borrow checker, it can be enhanced
> with it.
> A borrow checker has nothing tying it to the Rust syntax, so it should
> work.
>
> So I implemented a borrow checker for D, and it is enabled by adding the
> `@live`
> annotation for a function, which turns on the borrow checker for that
> function.
> There are no syntax or semantic changes to the language, other than laying
> on a
> borrow checker.
>
> Yes, it does data flow analysis, has semantic scopes, yup. It issues
> errors in
> the right places, although the error messages are rather basic.
>
> In my personal coding style, I have gravitated towards following the
> borrow
> checker rules. I like it. But it doesn't work for everything.
>
> It reminds me of OOP. OOP was sold as the answer to every programming
> problem.
> Many OOP languages appeared. But, eventually, things died down and OOP
> became
> just another tool in the toolbox. D and C++ support OOP, too.
>
> I predict that over time the borrow checker will become just another tool
> in the
> toolbox, and it'll be used for algorithms and data structures where it
> makes
> sense, and other methods will be used where it doesn't.
>
> I've been around to see a lot of fashions in programming, which is most
> likely
> why D is a bit of a polyglot language :-/
>
> I can also say confidently that the #1 method to combat memory safety
> errors is
> array bounds checking. The #2 method is guaranteed initialization of
> variables.
> The #3 is stop doing pointer arithmetic (use arrays and ref's instead).
>
> The language can nail that down for you (D does). What's left are memory allocation errors. Garbage collection fixes that.
>

On a slight tangent; why do I need to attribute the function at all for it
to check `scope` args don't escape?
I do want to add `scope` to pointers and ref arguments, but I don't see any
reason that I should have to attribute `live`... why isn't `scope` enough
to enable escape analysis?