It’s significantly more straight forward to go from a higher level to a lower level representation than it is to go between different high level representations.
That’s not to trivialize what a compiler does, but it’s effectively going from a complex form to its building blocks while maintaining semantics.
Changing high level languages introduces fundamentally different semantics. Both can decompose to the same general building blocks, but you can’t necessarily compose them the same way.
At the simplest example, a compiler backend (the part you’re describing) can’t reason about data access rules. That is the domain of the language’s compiler frontend and a fundamental difference between C++ and Rust that can’t just be directly derived.