Rust doesn't completely prevent logic errors like it does memory issues, but in practice I find they're much more rare. Rust's type system is very expressive and allows you to check many of your application invariants at compile time (see "Parse, don't validate": https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va...). In particular, I'd call out Rust's enums/discriminated unions as being probably the most impactful feature that's missing from many other programming languages.
From a more theoretical perspective, Rust's type system, ownership model, and borrow checker are general-purpose tools you can use to express compile-time-checked application invariants. The language and standard library use them to implement provably safe memory management, but you can also use them to prevent invalid states in your own applications or libraries. My understanding of the history of Rust's development is that the strong type system/ownership/lifetimes came first as a way of preventing logic bugs in complex concurrent applications, and only later the designers realized that system was powerful enough for full memory safety without garbage collection.
When I work with other programming languages, the experience of writing several hundred lines of code, compiling, and have them all work perfectly the first time is rare enough to be a surprise. When I write Rust, it's the norm.
I agree that "if it compiles it's correct" is a sloppy and possibly disingenuous statement. The compiler guarantees that your program is free from memory management errors and type errors; and it gives you the tools to turn most logic errors into type errors; but it does not guarantee absolute freedom from logic errors.
From a more theoretical perspective, Rust's type system, ownership model, and borrow checker are general-purpose tools you can use to express compile-time-checked application invariants. The language and standard library use them to implement provably safe memory management, but you can also use them to prevent invalid states in your own applications or libraries. My understanding of the history of Rust's development is that the strong type system/ownership/lifetimes came first as a way of preventing logic bugs in complex concurrent applications, and only later the designers realized that system was powerful enough for full memory safety without garbage collection.
When I work with other programming languages, the experience of writing several hundred lines of code, compiling, and have them all work perfectly the first time is rare enough to be a surprise. When I write Rust, it's the norm.
I agree that "if it compiles it's correct" is a sloppy and possibly disingenuous statement. The compiler guarantees that your program is free from memory management errors and type errors; and it gives you the tools to turn most logic errors into type errors; but it does not guarantee absolute freedom from logic errors.