Rust is complex, but I think it’s honest in its complexity: it straddles programmers with lifetime management in exchange for better optimizations (alias analysis is a pain in C!) and memory safety.
This is in contrast to C: it’s very easy to write C that compiles, but very difficult to fully evaluate its correctness. Part of that is the extraordinary complexity of the C abstract machine, combined with its leakiness: writing correct C requires you to understand both your ISA’s memory model and the set of constraints inconsistently layered on it by C. That’s a kind of pernicious complexity that Rust doesn’t have.
There is something true in what you are saying, but I still think the difference in complexity between Rust and C has much more to do with the very different goals of the languages rather than C just hiding complexity from the programmer.
Rust targets a much higher level of abstraction than C. The machine itself is at arms-length, and you are mostly thinking in terms of an abstract type system and borrow checker rather than a CPU and memory system. A lot of rust programming is declarative, and a lot of the complexity comes from finding the right way to express your intent to the compiler through the various systems of the language. The tradeoff for that complexity is that you get to write programs with very strong safety guarantees, correctness benefits, and low performance overhead.
C is about having simple, imperative control over the computer hardware. With C you are thinking in terms of the CPU and the memory system, you are mostly just telling the computer exactly what you want it to do.
C definitely does have some failings: for instance as you allude to, C doesn't ensure that all failure modes are encoded in the function signature, so it's not really possible to audit a C program for correctness by reading the source alone, the way you can almost do with Rust.
But that doesn't mean that the level of complexity which comes with Rust is necessary to fix the issues with C. Zig is a good example of trying to plug some of C's holes without increasing the level of abstraction.
Rust is complex, but I think it’s honest in its complexity: it straddles programmers with lifetime management in exchange for better optimizations (alias analysis is a pain in C!) and memory safety.
This is in contrast to C: it’s very easy to write C that compiles, but very difficult to fully evaluate its correctness. Part of that is the extraordinary complexity of the C abstract machine, combined with its leakiness: writing correct C requires you to understand both your ISA’s memory model and the set of constraints inconsistently layered on it by C. That’s a kind of pernicious complexity that Rust doesn’t have.