I don't think a borrow checker is likely to be in that tooling. Borrow checking requires shaping the code, and all the dependencies, into easily analyzable (and at least in rust's version annotated) patterns. You can't borrow check arbitrary code not designed for it without false positives.
x = malloc();
if (opaque_cond()) free(x);
if (other_opaque_cond()) use(x);
Conditions can be opaque and non-analyzable due to rices theorem - in any turing complete language. This code is correct (or at least not memory unsound) if opaque_cond and other_opaque_cond are never both true. Otherwise it isn't.And functionally compiler analyses of whether conditions hold have to be trivial because using some form of theorem prover to decide of code is correct or not leads to code that is brittle against compiler version changes, and slow compile times. Thus opaque_cond could be as simple as `len == 0` and `other_opaque_cond` could be `len > 0` and it's unlikely you'd want the compiler to realize those are mutually exclusive (at the stage where it accepts programs, obviously during optimization it is very likely to take advantage of this).
Rust solves this by simply rejecting the pattern. Very roughly forcing you to write if opaque_cond() { free(x) } else if other_opaque_cond() { use_x } (or something else where the program structure and not just the logic in the conditions guarantees correctness). Zig simply allows it and leaves it up to the programmer not to make a mistake.
And as onlyrealcuzzo suggests aliases are where this type of analysis (accepting enough programs to be useful but still imposing enough structure you can prove correctness) is really tricky.
Without affine/linear ownership - solving the aliasing problem is the Halting Problem.
Rust didn't invent Affine Ownership just to make Rust hard. It did it because it's one of the only ways to have memory safety without a GC.
Most of the goals on this page are targeted for this year.
I'm writing a language with Affine Ownership that transpiles to Zig and has a built-in FSM-based Green Fiber runtime.
Affine Ownership gives you memory safety + fearless concurrency + eliminates the need for Go's GC.
It's obviously going to slow down compilation - since you need to do Rust's borrow checking, etc. But I can do this incrementally as well...
The reason Rust has a working borrow checker is because every part of the language from structs, enum, traits, generics and all the way to the syntax itself has been designed to support lifetimes and borrow checking.
It's is not something you can just tack on to an existing language without fundamentally changing it.
As a simple example, Zig has no private fields. That makes encapsulating any unsafety impossible.
it is easy to patch the zig compiler to enable this this (export the code graph; about 50 LOC). The analysis is much much harder to get right.
You may have missed the point here. You could add a comment to the struct field that marks the field as private, and build a TypeScript/JSDoc analogue that analyzes all accesses to the field and fails if it finds accesses from functions that aren't part of the struct that owns the field. You don't even need a comment on the field - you could copy Go's convention, add a comment to the struct definition marking it as "follows Go convention", and then fail any access from outside the struct to a field that starts with a lower-case character.
It doesn't prevent you from ignoring that tool and writing Zig code that imports the struct and accesses the field. It is, of course, not part of the Zig language itself. But if you adopted a tool like that, it would be your responsibility to run it across-the-board and pay attention to the results - same as how it is your responsibility to pay attention to the results if you added those JSDoc comments.
Take another example: unsafe traits. They are fundamental to some safety encapsulations, most famously concurrency (`Send`/`Sync`). Here you cannot just build an analyzer to mark something unsafe, because Zig has no traits, its generics are duck-typed.
You can, of course, add traits. But at this point you're essentially creating your own language that compiles to Zig, with all problems this entails (e.g. bad ecosystem support). It's also hard to claim that Zig can be memory safe then.
Every part of the language must support memory safety from first principles.
SeL4C is formal verification, and while it can prove memory safety (and much more) it is much more difficult, to the point that you're basically programming in a different language.
Ada/SPARK is your best example, and also the example I know the least of, so I won't comment on.
The way Python added types is the most disgusting thing imaginable... but it has type hints now, so I guess that makes some people happy.
Why do you say that. Have you tried and failed? It seems to be possible to add a borrow checker to zig, just as you can add MIRI to rust to get extra safety in unsafe blocks.
It's doable, and as static analysis. see sibling comment.
Rust's borrow checker requires lifetime annotations. Zig code doesn't contain any such annotations. How does your design handle this?
I was fine with basic generics they complicated it quite a bit much for my liking.
In practice, Go can typically outperform Rust in throughput (using more memory), despite having a mountain of disadvantages against it in theory.
That's how good the Go scheduler/runtime is.
This is a huge claim that disagrees with both my real-world experience and everything I've seen from artificial comparisons.
Every high performance Go system I've worked on has quickly reached the point where we're optimizing memory management and doing things that would have been explicit in a non-GC language like Rust anyway.
The Go runtime is amazingly optimized, but it comes with overhead over doing the same work directly in a lower level language.
That seems unlikely regardless of how good it is. This is a domain where state-of-the-art research is not in the public literature. Scheduling is an AI-complete problem.
Rust itself doesn't have a scheduler of course, I assume this is comparing against tokio or one of the other async executors?
but yeah. i would be surprised if the JVM's scheduler is not more sophisticated than go's if for no other reason than it has way more knobs you can tune. you know they put that knob in there because someone (probably Google cough cough) asked for it
i periodically throw my unused codex tokens at this: