> With program redesigns that Rust requires

Why does Rust sometimes require program redesigns? Because these programs are flawed at some fundamental level. D lacks the most important and hardest kind of safety and that is reference safety - curiously C++ profiles also lacks any solution to that problem. A significant amount of production C++ code is riddled with UB and will never be made safe by repainting it and bounds checking.

Claiming that not being forced to fix something fundamentally broken is an advantage when talking about safety doesn't make you look like a particularly serious advocate for the topic.

> Why does Rust sometimes require program redesigns? Because these programs are flawed at some fundamental level.

I'm familiar with borrow checkers, as I wrote one for D.

Not following the rules of the borrow checker does not mean the program is flawed or incorrect. It just means the borrow checker is unable to prove it correct.

> D lacks the most important and hardest kind of safety and that is reference safety

I look at compilations of programming safety errors in shipped code now and then. Far and away the #1 bug is out-of-bounds array access. D has solved that problem.

BTW, if you use the optional GC in D, the program will be memory safe. No borrow checker needed.

> I look at compilations of programming safety errors in shipped code now and then. Far and away the #1 bug is out-of-bounds array access. D has solved that problem.

Do you have good data on that? Looking at the curl and Chromium reports they show that use-after-free is their most recurring and problematic issue.

I'm sure you are aware, but I want to mention this here for other readers. Reference safety extends to things like iterators and slices in C++.

> Not following the rules of the borrow checker does not mean the program is flawed or incorrect.

At a scale of 100k+ LoC every single measured program has been shown to be flawed because of it.

No, I haven't kept track of the reports I've seen. They all had array bounds as the #1 error encountered in shipped code.

Edit: I just googled "causes of memory safety bugs in C++". Number 1 answer: "Buffer Overflows/Out-of-Bounds Access"

"Undefined behavior in C/C++ code leads to security flaws like buffer overflows" https://www.trust-in-soft.com/resources/blogs/memory-safety-...

"Some common types of memory safety bugs include: Buffer overflows" https://www.code-intelligence.com/blog/memory_safety_corrupt...

"Memory Safety Vulnerabilities 3.1. Buffer overflow vulnerabilities We’ll start our discussion of vulnerabilities with one of the most common types of errors — buffer overflow (also called buffer overrun) vulnerabilities. Buffer overflow vulnerabilities are a particular risk in C, and since C is an especially widely used systems programming language, you might not be surprised to hear that buffer overflows are one of the most pervasive kind of implementation flaws around." https://textbook.cs161.org/memory-safety/vulnerabilities.htm...

Spatial safety can be achieved exhaustively with a single compiler switch - in clang - and a minor performance hit. Temporal safety is much harder and requires software redesign, that's why it still remains in projects that care about memory-safety and try over a long time to weed out all instances of UB, i.e. critical software like curl, Linux and Chromium.

Temporal safety is usually also much harder to reason about for humans, since it requires more context.

What flag is that? Address sanitizer has a 2x performance hit so presumably not that?

-fbounds-safety [1]

Based on their slides [2]. I was wrongly informed one does need to do some light annotation in function signatures and struct definitions for anything ABI relevant. Based on their slides:

Ptrdist and Olden benchmark suites

- LOC changes: 2.7% (0.2% used unsafe constructs) Much lower than prior approaches

- Compile-time overhead: 11%

- Code-size (text section) overhead: 9.1% (ranged -1.4% to 38%)

- Run-time overhead: 5.1% (ranged -1% to 29%)

Measurement on iOS

- 0-8% binary size increase per project

- No measurable performance or power impact on boot, app launch

- Minor overall performance impact on audio decoding/encoding (1%)

[1] https://clang.llvm.org/docs/BoundsSafety.html

[2] https://llvm.org/devmtg/2023-05/slides/TechnicalTalks-May11/...

> Why does Rust sometimes require program redesigns? Because these programs are flawed at some fundamental level.

Simply not true, and this stance is one of the reasons we have people talking about Rust sect.

> Because these programs are flawed at some fundamental level.

No. Programs that pass borrow checking are a strict subset of programs that are correct with respect to memory allocation; an infinite number of correct programs do not pass it. The borrow checker is a good idea, but it's (necessarily) incomplete.

Your claim is like saying that a program that uses any kind of dynamic memory allocation at all is fundamentally broken.

> Because these programs are flawed at some fundamental level.

That's a very strong statement. How do you support it with arguments?

We have strong evidence that anything with 100k+ LoC that uses C or C++ will have use-after-free bugs because of reference semantics. I have no data on D but I wouldn't be surprised if that's the same case there as well. You need to think about ownership and haphazardly treating it as a free-for-all is a fundamental design flaw IMO. Shared mutable state is bad for the same reasons mutable global variables are frowned upon. One needs to keep the sum total of all places and all possible paths leading to them in context for reasoning about any of them. This very very quickly becomes intractable for human minds.