Hacker News new | past | comments | ask | show | jobs | submit login

Static analysis of arbitrary legacy code is limited. But I do not find it difficult to structure my code in a way that I can reasonable exclude most errors. The discussion of false positives in C is interesting. In some sense, 99% of what the Rust compiler would complain about would be considered false positives in C. So if you want to have safety in C, you can not approach this from this angle. But this relates to my point. If it is acceptable to structure the code in specific ways to make the Rust compiler happy, but you do not accept that you may have to write code in specific ways to avoid false positives in C, then you are already not comparing apples to apples.



Even if you rewrite C code to the same "shape" as Rust, it won't become equally easy to statically analyze. The C language doesn't give the same guarantees, so it doesn't benefit from the same restrictions. For example, pointers don't guarantee their data is always initialized, `const` doesn't make the data behind it truly immutable, and there's no Send/Sync to describe thread safety. You have nothing to express that a piece of memory has a single owner. C's type system also loses information whenever you need to use void* instead of generics, unions with a DIY tag, and have pointers with a mixed provenance/ownership.

Rust checks that you adhere to the analyzable structure, and keeps you from accidentally breaking it at every step. In C you don't get any compiler help for that. I'm not aware of any tools that guide such structure for C beyond local tweaks. It'd be theoretically possible with enough non-standard C language extensions (add borrowing, exclusive ownership with move semantics), but that would get pretty close to rewriting the code in Rust, except using a bolted-on syntax, a dumb compiler that doesn't understand it, and none of the benefits of the rest of Rust's language, tooling, and ecosystem.


You do not get the same automatic guarantees when not using external tools. But you get almost the same results when using tools readily available and having a good strategy for organizing. I do not have problems with double frees, void type unsafety, or tagged unions in my code. I occasionally have memory leaks, which tooling then tends to find. I certainly have exploitable integer overflows, but those are easily and comprehensively mitigated by UBsan.


> If it is acceptable to structure the code in specific ways to make the Rust compiler happy

I think this is a misleading way of presenting the issue. In Rust, there are class of bugs that no valid Rust code can have (unless maybe when using the "unsafe" keyword), while there is valid C code that has said bugs. And here's the difference: in Rust the compiler prevents some mistakes for you, while in C it is you that have to exercise discipline to make sure every single time you structure the code in such a way to make said bugs unlikely. From this, it follows that Rust code will have less (memory-related) bugs.

It is not an apples to apples comparison because Rust is designed to be a memory safe fruit, while C isn't.


The point was that you can not reject warnings as part of a solution for C because "it annoys programmers because it has false positives" while accepting Rust's borrow checker as a solution.


I think the general point of my comment still stands, as you and everyone else working on the project would need to be disciplined and only release binaries that were compiled with no warnings. And even using -Werror doesn't fully solve the problem in C, as not having warnings/errors is still not enough to get memory safety.


I don't really disagree with you, but I was also making a slightly different point. If you need absolute memory safety, you can use Rust (without ever using unsafe)

But you get 99% this way with C, a bit of discipline, and tooling and this also means maintaining a super clean code base with many warnings activated even though they cause false positives. My point is that these false positives are not a valid argument why this strategy does not work or is inferior.

Your claim is that it is inferior because you only get 99% of safety and not 100%. But one can question whether you actually get 100% in Rust in practice in a project of relevant size and complexity, due to FFI and unsafe. One can also question whether 100% memory safety is all that important when there also many other issues to look out for, but this is a different argument.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: