C++ tool that takes care of errors as it’s done in Rust compiling

I was not sure where to ask my question. So, I ended up asking here. Please ignore my question if it's off-topic on this forum.

I'm a C++ developer who wants to enjoy the same advantages that the Rust compiler provides. I'm looking for a C++ tool to enforce what the Rust compiler enforces. Is there such a C++ tool out there? Or is it just a pipe dream?

The Rust language was purposefully designed so that the compiler can make those checks. I know there's some C++ static analysis tools that can catch some mistakes and enforce certain rules (I don't know what they're called), but it won't be exactly like Rust, especially because other libraries don't contain the machine-readable information that is built-into Rust libraries with respect to borrows and thread safety.

However, one of the focuses of Rust is being interoperable with other languages, so you can mix C++ and Rust in one codebase if you are interested in trying it out or rewriting your C++.

2 Likes

That really is a question for the C++ community. There are things like the C++ Core Guidelines and related static analysis tools that are meant to increase C++ safety, but you really should find out more about that from the people who know (C++ programmers). Is there a C++ forum of some kind?

3 Likes

Many C++ users check their code for memory misuse errors, data race errors etc using tools such as address sanitiser (asan) thread sanitiser (tsan) and perhaps other analysers I have forgotten about.

These analysers don't do static analysis they detect problems at run time. Which means you have to run your code as tests or a full program to let the detect any problems, Performance is impacted so not usable in production running.

There is also valgrind: Valgrind

I imagine mixing C++ and Rust is more of a pain than one would like. Rust has good interop with C but does not understand the higher level abstractions of C++.

2 Likes

Have you watched the big C++ convention presentations from the last few years[*]? (Especially those relating to "safety").

Several of the C++ Elders (Bjarne (in particular), Sutter, et al) have argued that C++ can, more or less, do everything that all other languages can (with regard to safety) -- you just need to use the resources that are available. Specifically:

  • Use the C++ Core Guidelines
  • Use static analyzers
  • Use sanitizers

As someone who has done all that, I vehemently disagree that this gets you to the level of confidence in your code that Rust provides, but it is the current state of the art for getting as close to Rust as possible with C++. (Just to be clear -- while it isn't Rust, I do think there's great value in following these tips).

Though I will note that Bjarne has also stated that the C++ static analysis tools need to get better, and the only way for them to get better is for people to use them and report problems/limitations. (And that in itself seems to be a problem -- C++ developers, in my experience, refuse to use static analyzers).

We're moving away from C++, but if we were looking to continue using it we'd probably use Sutter's cppfront (once it has matured).

[*] Mini-rant: One thing that I find annoying while watching these presentations is that they keep on insisting that they solved all of today's language safety issues back in the later part of the 1980 -- it's just that they haven't gotten around to implementing all these solutions in the language yet. "Look, here's a note I wrote in 1991 about memory safety!" (shows a note which simply states "Make things better"). But even if those claims were true: What use is a crystal ball that can foresee the needs of the future if you're only going to use that knowledge to write spiffy one-liners in presentations several decades later?

6 Likes

On thing that they tend to ignore 100% is the fact that problem of C++ unsafety is partially the language, but more important it's the culture that exist among language users.

Both C++ and Rust have range-checking access operator and unchecked access operator for arrays, but what is used when the most obvious arr[i] syntax is used, hmm?

They talk about how they had some ideas about safety decades ago and about how Ada community added safety to memory allocations their language, and then they postulate two statements which always make me laugh:

  1. C++ is with us for many years yet, because there are billions lines of the code written in it.
  2. C++ problems with safety may be fixed (in a way Ada did that by lifting features from Rust or in some other way).

Yes, it's true: both statements are valid… yet they are incompatible: what good the fact that “new fixed C++” is safe if all your codebase is full of “old, bad and unsafe C++” and you need to rewrite everything?

If you still have to rewrite everything then why use C++ to do that? And if you don't plan to rewrite everything then how may all these wonderful tools help you?

They would still be unable to resolve issues with lifetimes if rules are never stated anywhere and thus can not be checked!

7 Likes

To add to that on a technical level, many properties of the type system such as specifying a function as unsafe, various auto-traits and in particular Send, Sync need to be in the language and actively added by the programmer. Any form of automatic deduction will run into Rice's theorem. It's not feasible and on top of that a specification of 'deduce the upper bound of possible attributes' even if it would be feasible to compute can not be reasoned about reliably. Whose brain is an effective SAT-solver and why should it need to be. The core observation is that (parts of) the infeasibility goes away by choosing to restrict the language to the non-general case, which C++ refuses to do time and time again. It really sets itself a mathematically impossible task, I feel.

Considering those restrictions, really what you're talking about is a need for a language that enables those tools, which makes it possible for types and values to transport facts as separable invariants. And that language is just Rust. The idea that somehow tools would allow re-use of existing C++ code without modification but 'now safe' is a delusion you must rid yourself of. You must restrict the language and that will cause rewrites of programs that then fall outside the restrictions. Quantifying the amount is something that can be engineered to a degree, yet an empirical evaluation of such seems to have never been done in C++.

The tools you talk about would require almost precisely the same amount of type reasonings as Rust does, in a different syntax or a different source maybe, since having explicit trait impls and other qualifing annotations added by the programmer is why rustc works. The type system does a whole lot of constructive non-boolean reasoning in overlap checks of impls, etc. This is necessary for soundness guarantees, particular those around forward compatibilities. Since the compiler requires them from the programmer, those annotations are intentionally added where it is necessary, much more in the core types than a typical user encounters but still user code can and does refer to them, and properly using the type system in this way is a fundamental aspect of writing good Rust.

There is no conceptual difference between rewriting in Rust and rewriting into C++-with-tons-of-yet-to-be-defined annotations and some form of monotonic type-reasoning, except for the timelag it'll take to get ISO consensus over what that specifiction should be.

Ergo: The software you're looking for is called rustc.

5 Likes

I have heard this a few time also. I have even heard Bjarne saying that C++ could evolve to do provide the memory safety that Rust does and "so it better". I find it hard to understand how that is even possible without totally breaking compatibility with the huge existing base of C++. I guess new C++ would need to introduce the equivalent of "unsafe" and treat old C++ as a foreign language.

As it stands one needs to check every statement in C++ that one writes, in the context it is written, against the thousand or so pages of core guideline rules. That strikes me as a tremendously tedious, error prone, labour intensive task that is an idea candidate for automation. Enter Rust that does exactly that.

Then the analysers are not fool proof and the sanitizers require one to run all of the code, with all possible data inputs, to achieve any effectiveness.

In the face of all that I just don't see how Barne and others can be right.

4 Likes