Most languages have some C interop, and that satisfies the minimal definition of "incremental".
However, using C and C++ together in a project is especially easy. If I were to do this, I would first get the code base compiling with a C++ compiler (this already brings some extra type safety) and is not particularly difficult.
Then I'd start replacing C code blocks with safer C++ code. This could mean changing a function, some parameter-passing conventions, replacing char* with std::string, etc.
This has the biggest chance of success I feel, and there's already success stories and strategies available that describe this method. E.g: GCC.
Rust <-> C interop is pretty strong. AFAIK, there is equivalent call overhead between Rust & C as there is between C & C++ (i.e. none). You're right that incrementally porting to Rust would be a little bit more overhead than C++, simply because you'd need two compilers, and instead of rewriting function definitions in-place you'd need to write a fresh function in Rust and delete it in C. But at link time everything is sane and once you set up the build, it's really not hard.
I'm not suggesting that C -> Rust is easier than or quite as easy as C -> C++, just that it is much easier than C -> most other languages, and that it is close enough to C -> C++ that it is worth investigating. It is definitely more robust than the minimal definition of "incremental."
However, using C and C++ together in a project is especially easy. If I were to do this, I would first get the code base compiling with a C++ compiler (this already brings some extra type safety) and is not particularly difficult.
Then I'd start replacing C code blocks with safer C++ code. This could mean changing a function, some parameter-passing conventions, replacing char* with std::string, etc.
This has the biggest chance of success I feel, and there's already success stories and strategies available that describe this method. E.g: GCC.