Not really possible, I think. C is a language that's basically built on memory aliasing and pointer arithmetic: every variable is represented as a location in memory, but there is no guarantee that each memory location is only represented once (there can be many variables pointing to the same memory address). The Rust borrow checker needs pretty much the opposite guarantee: every declared variable has full control over its memory location, and if two pieces of code need to share memory there needs to be an explicit protocol for delegating access.
And it's not like pointers are a rare occurrence in C. This mechanism is used pretty much everywhere: accessing array values, parameter pass-by-reference, function output parameters, string manipulation. There's no concept of function purity either, so no way to guarantee in the function definition that a function cannot outstep its bounds. Sure, there are certain safe coding conventions and rules about what you can or cannot do in a C program, but fundamentally proving that a certain memory location is only accessed through a certain variable is only possible by just running the program exhaustively -- or by confining yourself to a subset of C.
But when you only allow a subset of C, it's no longer "C with a borrow checker", especially given the ubiquitous use of pointers for standard language features. It quickly becomes "we hobbled C because we need more guarantees". To take a quote from the D manual [0], to guarantee memory safety you need to disallow:
- Casts that break the type system.
- Modification of pointer values.
- Taking the address of a local variable or function parameter.
> C is a language that's basically built on memory aliasing
Additionally, C does actually have aliasing rules, but many projects, including the kernel, turn them off. Linus in particular does not think they're worthwhile.
These rules are different than Rust's, Rust also rejected these particular rules.
> To take a quote from the D manual [0], to guarantee memory safety you need to disallow
Just to be clear, this is the list for D, not in general. Rust is fine with you taking the address of a local variable or function parameter.
If you're referring to e.g. gcc's -f[no-]strict-aliasing option, then that's more about type compatibility than about limiting the scope of memory aliasing in general. If you mean something else, I'm interested to hear more.
> this is the list for D, not in general
Yes, I know. But it's the first authoritative source I could think of on memory safety in C-like languages. I don't think the list is wrong for C proper, just probably not exhaustive.
> Rust is fine with you taking the address of a local variable
Yes! But circling back to the earlier point: in Rust you can do this specifically because the language has well-defined lifetime semantics on variables and ownership. And as such, Rust can guarantee that a) a pointer to a memory location does not outlive the scope of the memory allocation itself, and b) when two variables/pointers refer to the same memory location, there is a compiler-enforced protocol for accessing and mutating that memory.
And it's not like pointers are a rare occurrence in C. This mechanism is used pretty much everywhere: accessing array values, parameter pass-by-reference, function output parameters, string manipulation. There's no concept of function purity either, so no way to guarantee in the function definition that a function cannot outstep its bounds. Sure, there are certain safe coding conventions and rules about what you can or cannot do in a C program, but fundamentally proving that a certain memory location is only accessed through a certain variable is only possible by just running the program exhaustively -- or by confining yourself to a subset of C.
But when you only allow a subset of C, it's no longer "C with a borrow checker", especially given the ubiquitous use of pointers for standard language features. It quickly becomes "we hobbled C because we need more guarantees". To take a quote from the D manual [0], to guarantee memory safety you need to disallow:
[0] https://dlang.org/spec/memory-safe-d.html